如何使用xargs复制名称中带有空格和引号的文件?
我正在尝试在目录下复制一堆文件,并且其中一些文件的名称中包含空格和单引号。当我尝试将find
和grep
与xargs
串在一起时,出现以下错误:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar xargs: unterminated quote
关于更可靠地使用xargs的任何建议?
这是在带有BSDxargs
的MacOSX 10.5.3(Leopard)上。
解决方案
找到。 -print0 | grep --null'FooBar'| xargs -0 ...
我不知道Leopard上grep是否支持--null或者xargs是否支持-0,但是在GNU上都很好。
考虑将xargs的--null命令行选项与find中的-print0选项一起使用。
我们可以将所有这些组合到一个" find"命令中:
find . -iname "*foobar*" -exec cp -- "{}" ~/foo/bar \;
这将处理文件名和目录中带有空格的内容。我们可以使用-name获得区分大小写的结果。
注意:传递给cp
的--
标志阻止它处理以-
开头的文件作为选项。
这会更有效,因为它不会多次运行" cp":
find -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar
请注意,其他答案中讨论的大多数选项在不使用GNU实用程序的平台(例如Solaris,AIX,HP-UX)上不是标准的。有关"标准" xargs行为,请参见POSIX规范。
我还发现xargs的行为,即使没有输入,它至少运行一次命令也很麻烦。
我写了自己的专用版本的xargs(xargl)来解决名称中的空格问题(尽管'find ... -print0'和'xargs -0'的组合很整洁,但考虑到文件名不能包含空格,只有换行符分开了) ASCII NUL'\ 0'字符,我的xargl不够完善,值得发布,尤其是因为GNU的功能至少还不错。
我发现以下语法非常适合我。
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字节。
在" find"和" xargs"之间的Perl线性行对每个空格进行转义/引用,因此" xargs"将任何带有嵌入式空格的文件名传递给" ls"作为单个参数。
bill_starr的Perl版本不适用于嵌入式换行符(只能处理空格)。对于那些没有GNU工具的Solaris,可能是更完整的版本(使用sed)...
find -type f | sed 's/./\&/g' | xargs grep string_to_find
根据需要调整find和grep参数或者其他命令,但是sed将修复嵌入式换行符/空格/制表符。
我使用了在Solaris上稍作修改的Bill Star的答案:
find . -mtime +2 | perl -pe 's{^}{\"};s{$}{\"}' > ~/output.file
这将在每行周围加上引号。我没有使用'-l'选项,尽管它可能会有所帮助。
我要访问的文件列表可能带有'-',但是没有换行符。我没有将输出文件与任何其他命令一起使用,因为在我开始通过xargs大规模删除它们之前,我想回顾一下发现的内容。