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

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

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

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


当前回答

我也遇到了同样的问题。以下是我的解决方法:

find . -name '*FoooBar*' | sed 's/.*/"&"/' | xargs cp ~/foo/bar

我使用sed将每一行输入替换为同一行,但是用双引号括起来。在sed手册页中,“…替换中出现的&号('' & ")将被匹配RE…"的字符串替换。"——在本例中,.*表示整行。

这解决了xargs: unterminated quote错误。

其他回答

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

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

此方法适用于Mac OS X v10.7.5 (Lion):

find . | grep FooBar | xargs -I{} cp {} ~/foo/bar

我还测试了你发布的确切语法。这在10.7.5上也能正常工作。

我尝试了一下,开始考虑修改xargs,并意识到对于我们在这里讨论的这种用例,用Python简单地重新实现是一个更好的主意。

首先,整个事情有大约80行代码意味着很容易弄清楚发生了什么,如果需要不同的行为,你可以在更短的时间内把它黑进一个新的脚本,而不是在Stack Overflow等地方得到回复。

参见https://github.com/johnallsup/jda-misc-scripts/blob/master/yargs和https://github.com/johnallsup/jda-misc-scripts/blob/master/zargs.py。

使用编写好的yargs(并且安装了Python 3),您可以键入:

find .|grep "FooBar"|yargs -l 203 cp --after ~/foo/bar

一次拷贝203个文件。(这里203只是一个占位符,当然,使用像203这样奇怪的数字可以清楚地表明这个数字没有其他意义。)

如果你真的想要更快,不需要Python,可以把zargs和yargs作为原型,然后用c++或C重写。

最简单的方法来做原来的海报想要的是改变分隔符从任何空白到只是行结束字符,像这样:

find whatever ... | xargs -d "\n" cp -t /var/tmp

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

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

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

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

这个解决方案:

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

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