我试图复制一堆文件下面的目录和一些文件有空格和单引号在他们的名字。当我尝试用xargs将find和grep串在一起时,我得到以下错误:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
对于更健壮地使用xargs有什么建议吗?
这是在Mac OS X 10.5.3 (Leopard)上使用BSD xargs。
我试图复制一堆文件下面的目录和一些文件有空格和单引号在他们的名字。当我尝试用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 whatever ... | xargs -d "\n" cp -t /var/tmp
其他回答
此方法适用于Mac OS X v10.7.5 (Lion):
find . | grep FooBar | xargs -I{} cp {} ~/foo/bar
我还测试了你发布的确切语法。这在10.7.5上也能正常工作。
请注意,其他答案中讨论的大多数选项在不使用GNU实用程序的平台上都不是标准的(例如Solaris、AIX、HP-UX)。关于“标准”xargs行为,请参阅POSIX规范。
我还发现xargs的行为,即它至少运行一次命令,即使没有输入,这是一个麻烦。
我写了我自己的xargs (xargl)的私人版本来处理名称中的空格问题(只有换行符分开-尽管'find…-print0'和'xargs -0'的组合非常简洁,因为文件名不能包含ASCII NUL '\0'字符。我的xargl还没有完整到值得发布的程度——特别是因为GNU的工具至少和它一样好。
最简单的方法来做原来的海报想要的是改变分隔符从任何空白到只是行结束字符,像这样:
find whatever ... | xargs -d "\n" cp -t /var/tmp
我尝试了一下,开始考虑修改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,例如ls:
find . | grep "FooBar" | tr \\n \\0 | xargs -0 -I{} cp "{}" ~/foo/bar