如何使用xargs复制名称中带有空格和引号的文件?

时间:2020-03-06 14:49:13  来源:igfitidea点击:

我正在尝试在目录下复制一堆文件,并且其中一些文件的名称中包含空格和单引号。当我尝试将findgrepxargs串在一起时,出现以下错误:

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大规模删除它们之前,我想回顾一下发现的内容。