我试图复制一堆文件下面的目录和一些文件有空格和单引号在他们的名字。当我尝试用xargs将find和grep串在一起时,我得到以下错误:

find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote

对于更健壮地使用xargs有什么建议吗?

这是在Mac OS X 10.5.3 (Leopard)上使用BSD xargs。


当前回答

这更有效,因为它不会多次运行“cp”:

find -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar

其他回答

我发现下面的语法很适合我。

find /usr/pcapps/ -mount -type f -size +1000000c | perl -lpe ' s{ }{\\ }g ' | xargs ls -l | sort +4nr | head -200

在本例中,我正在查找挂载在“/usr/pcapps”的文件系统中最大的200个超过1,000,000字节的文件。

Perl在“find”和“xargs”之间的行- - -转义/引用每个空白,因此“xargs”将任何带有嵌入空白的文件名作为单个参数传递给“ls”。

框架挑战-你正在询问如何使用xargs。答案是:不使用xargs,因为不需要它。

user80168的注释描述了一种直接使用cp的方法,而不需要对每个文件调用cp:

find . -name '*FooBar*' -exec cp -t /tmp -- {} +

这很有效,因为:

cp -t标志允许在靠近cp开头的位置给出目标目录,而不是靠近结束的位置。来自男人cp:

- t,目标目录=目录 将所有SOURCE参数复制到DIRECTORY中

——标志告诉cp将后面的所有内容解释为文件名,而不是标志,因此以-或——开头的文件不会混淆cp;您仍然需要这样做,因为-/——字符由cp解释,而任何其他特殊字符由shell解释。 find -exec命令{}+变体本质上与xargs相同。从人类发现:

-exec command {} + This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invoca‐ matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of `{}' is allowed within the command, and (when find is being invoked from a shell) it should be quoted (for example, '{}') to protect it from interpretation by shells. The command is executed in the starting directory. If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status. If find encounters an error, this can sometimes cause an immedi‐ ate exit, so some pending commands may not be run at all. This variant of -exec always returns true.

通过直接在find中使用它,就避免了管道或shell调用的需要,这样您就不需要担心文件名中任何讨厌的字符。

对我来说,我想做一些不一样的事情。我想复制我的txt文件到我的tmp文件夹。txt文件包含空格和撇号。这在我的Mac上很管用。

$ find . -type f -name '*.txt' | sed 's/'"'"'/\'"'"'/g' | sed 's/.*/"&"/'  | xargs -I{} cp -v {} ./tmp/

我使用了Bill Star在Solaris上稍作修改的回答:

find . -mtime +2 | perl -pe 's{^}{\"};s{$}{\"}' > ~/output.file

这将在每行周围加上引号。我没有使用“-l”选项,尽管它可能会有所帮助。

我要去的文件列表可能有'-',但没有换行符。我没有使用输出文件与任何其他命令,因为我想回顾什么是发现之前,我只是开始大规模删除他们通过xargs。

你可能需要像这样grep Foobar目录:

find . -name "file.ext"| grep "FooBar" | xargs -i cp -p "{}" .