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

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

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

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


当前回答

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

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

其他回答

只是不要使用xargs。这是一个简洁的程序,但当面对非平凡的情况时,它不太适合find。

这是一个可移植的(POSIX)解决方案,即不需要find, xargs或cp GNU特定的扩展:

find . -name "*FooBar*" -exec sh -c 'cp -- "$@" ~/foo/bar' sh {} +

注意结尾的+而不是更常见的;。

这个解决方案:

正确处理带有嵌入空格、换行符或任何外来字符的文件和目录。 适用于任何Unix和Linux系统,即使是那些没有提供GNU工具包的系统。 不使用xargs,这是一个很好的有用的程序,但需要太多的调整和非标准特性来正确处理查找输出。 也比公认的和大多数(如果不是全部的话)其他答案更有效(读得更快)。

还要注意,尽管在其他一些回复或评论中声明了什么,引用{}是无用的(除非您使用的是异国情调的fishshell)。

找到。-print0 | grep——null 'FooBar' | xargs -0…

我不知道grep是否支持-null,也不知道xargs是否支持-0,在Leopard上,但在GNU上都很好。

对于那些依赖命令,而不是find,例如ls:

find . | grep "FooBar" | tr \\n \\0 | xargs -0 -I{} cp "{}" ~/foo/bar

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

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

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

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

bill_starr的Perl版本不能很好地用于嵌入换行符(只处理空格)。对于那些没有GNU工具的Solaris,一个更完整的版本可能是(使用sed)…

find -type f | sed 's/./\\&/g' | xargs grep string_to_find

根据需要调整find和grep参数或其他命令,但sed将修复嵌入的换行符/空格/制表符。