xargs/exec 的参数列表太长

xargs/exec 的参数列表太长

我在 CentOS 服务器上工作,必须移动和整理数百万个文件。我尝试过许多类似下面的方法,但都失败了,并出现参数列表太长的错误。

命令:

find ./ -iname out.* -type f -exec mv {} /home/user/trash
find ./paramsFile.* -exec cat > parameters.txt 

错误:

-bash: /usr/bin/find: Argument list too long
-bash: /bin/cat: Argument list too long

或者

echo ./out.* | xargs -I '{}' mv /home/user/trash
(echo ./paramsFile.* | xargs cat) > parameters.txt  

错误:

xargs: argument line too long
xargs: argument line too long              

第二条命令也从未完成。我听说过一些关于通配符的事情,但我不确定我是否完全理解它。欢迎提供任何提示或建议!

答案1

您犯了多个错误。您应该避免*使用通配符。您必须将其放在{}引号之间(为了文件名安全),并且必须以-exec结尾\;

find ./ -iname out.\* -type f -exec mv "{}" /home/user/trash \;
find -name ./paramsFile.\* -exec cat "{}" >> parameters.txt \;

这里的问题是,它*匹配了目录中的所有文件,因此给出了错误。如果find定位文件而不是使用 shell 通配符,xargs则会获取可用于构造正确长度的行的单个文件名。

答案2

尝试这个:

find . -iname 'out.*' -type f -exec mv '{}' /home/user/trash \;
find . -name 'paramsFile.*' -print0 | xargs -0 cat >> parameters.txt

>>是为了确保多次调用cat(如果您确实有大量文件)输出到同一个文件,而不会覆盖先前调用的结果。另外,确保从parameters.txt空文件开始(或先将其删除)。

答案3

我目前手边没有一个盒子可以给出一个很好的(即经过测试的)答案,但我认为这是一个很好的用途parallel

如果我理解正确的话,你的命令

find ./ -iname out.* -type f -exec mv "{}" /home/user/trash

正在发出一个巨大的命令:

mv out.1 out.2 out.3 out.4 ... out.10100942 /home/user/trash

相反,

find ./ -iname out.* -type f | parallel mv "{}" /home/user/trash

将执行数百万个较小的命令:

mv out.1 /home/user/trash
mv out.2 /home/user/trash
...

您可能需要研究一些parallel选项,特别是-j-i这样你就不会意外地导致服务器过载。

PS. 遵循@Bernhard 的建议,每当您使用 shell 变量时,尤其是对于用户输入,请引用它!"{}"不要{}

相关内容