rm、cp、mv 命令的参数列表太长错误

新手上路,请多包涵

我在 UNIX 的一个目录下有数百个 PDF。 PDF 的名称非常长(大约 60 个字符)。

当我尝试使用以下命令一起删除所有 PDF 时:

 rm -f *.pdf

我收到以下错误:

 /bin/rm: cannot execute [Argument list too long]

这个错误的解决方案是什么? mvcp 命令是否也会出现此错误?如果是,如何解决这些命令?

原文由 Vicky 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

发生这种情况的原因是因为 bash 实际上将星号扩展到每个匹配的文件,从而产生了很长的命令行。

尝试这个:

 find . -name "*.pdf" -print0 | xargs -0 rm

警告: 这是一个递归搜索,也会在子目录中查找(并删除)文件。仅当您确定不想确认时,才将 -f 添加到 rm 命令。

您可以执行以下操作以使命令非递归:

 find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm

另一种选择是使用 find 的 -delete 标志:

 find . -name "*.pdf" -delete

原文由 DPlusV 发布,翻译遵循 CC BY-SA 4.0 许可协议

tl;博士

这是对命令行参数大小的内核限制。改用 for 循环。

问题的根源

这是一个系统问题,与 execveARG_MAX 常量有关。有很多关于这方面的文档(参见 man execvedebian 的 wikiARG_MAX details )。

基本上,扩展会产生一个超过 ARG_MAX 限制的 _命令_(及其参数)。在内核 2.6.23 上,限制设置为 128 kB 。此常量已增加,您可以通过执行以下操作来获取其值:

 getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

解决方法:使用 for 循环

使用 for 循环,因为它在 BashFAQ/095 上被推荐并且除了 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 评论)。

参考

原文由 Édouard Lopez 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题