我在 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 变量时,尤其是对于用户输入,请引用它!"{}"
不要{}
。