我在 UNIX 的目录下有几百个 PDF。 PDF 的名称非常长(约 60 个字符)。
当我尝试使用以下命令一起删除所有 PDF 时:
rm -f *.pdf
我收到以下错误:
/bin/rm: cannot execute [Argument list too long]
该错误的解决方法是什么? mv
和cp
命令也会发生此错误吗?如果是,如何解决这些命令?
发生这种情况的原因是 bash 实际上将星号扩展到了每个匹配的文件,从而产生了很长的命令行。
试试这个:
find . -name "*.pdf" -print0 | xargs -0 rm
警告:这是递归搜索,还将在子目录中查找(和删除)文件。仅在确定不希望确认时,才将-f
您可以执行以下操作使命令非递归:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
另一种选择是使用 find 的-delete
标志:
find . -name "*.pdf" -delete
这是命令行参数大小的内核限制。请使用for
循环。
这是一个系统问题,与execve
和ARG_MAX
常数有关。有很多关于此的文档(请参阅debian 的 wiki man execve )。
基本上,扩展产生的命令(及其参数)超过ARG_MAX
限制。在内核2.6.23
,该限制设置为128 kB
。该常量已增加,您可以通过执行以下操作获取其值:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
for
循环按照 BashFAQ / 095的建议使用for
循环,并且除了 RAM / 内存空间外没有其他限制:
空运行以确定其将删除您的期望:
for f in *.pdf; do echo rm "$f"; done
并执行它:
for f in *.pdf; do rm "$f"; done
这也是一种可移植的方法,因为 glob 在 shell 之间具有强大且一致的行为( POSIX 规范的一部分)。
注意:正如一些评论所指出的那样,这确实较慢,但更易于维护,因为它可以适应更复杂的场景,例如,一个人想做的不只是一项动作。
find
如果您坚持要使用,则可以使用find
但实际上不要使用 xargs,因为它“在读取非 NUL 分隔的输入时是危险的(损坏,可利用等)” :
find . -maxdepth 1 -name '*.pdf' -delete
使用-maxdepth 1 ... -delete
代替-exec rm {} +
可以使find
自己简单地执行所需的系统调用,而无需使用外部进程,因此速度更快(感谢@chepner comment )。
find
具有-delete
操作:
find . -maxdepth 1 -name '*.pdf' -delete