【问题标题】:"Argument list too long" error when passing a find output as arguments将查找输出作为参数传递时出现“参数列表太长”错误
【发布时间】:2021-01-14 11:58:40
【问题描述】:

我在一个目录下有大约 500 万个文本文件 - 所有格式都相同(没什么特别的,只是每行带有一些整数的纯文本文件)。我想计算所有这些文件中的最大和最小行数,以及它的两个文件名(一个用于最大值,另一个用于最小值)。

我开始尝试像这样写出所有的行数(然后练习如何从这个列表中找到最小值和最大值):

wc -l `find /some/data/dir/with/text/files/ -type f` > report.txt

但这会给我一个错误:

bash: /usr/bin/wc: 参数列表太长

也许有更好的方法来解决这个问题?

【问题讨论】:

  • 请注意,在命令行中使用 $(find ...)$(ls ...) 通常是一种不好的做法 - 请参阅 BashPitfalls #1UsingFind 描述的替代方法。
  • ...顺便说一句,鉴于您有数百万个文件,我会考虑在运行行数之前过滤字节数;除非您在行长方面容易出现异常值,否则仅扫描 100,000 个最大和最小文件(以字节为单位,这是一种恒定时间测量操作而不是一个随大小缩放)以行为单位。

标签: python bash wc


【解决方案1】:

参数列表长度有一个limit。由于您有数百万个文件传递给 wc,因此该命令肯定越过了这条线。

最好调用find -exec COMMAND

find /some/data/dir/with/text/files/ -type f -exec wc -l {} + > report.txt

在这里,每个找到的文件find 将附加到-exec 之后的命令的参数列表中,而不是{}。在达到参数长度之前,将运行命令,并且将在新的命令运行中以相同的方式处理剩余的找到的文件,直到完成整个列表。

更多详情请参阅find 中的man page


感谢 Charles Duffy 对此答案的改进。

【讨论】:

  • 我不能代表反对意见,但我强烈建议将-exec ... {} \; 更改为-exec ... {} +;事实上,这是非常低效的(为每个文件启动 wc 的新副本,而不是仅在参数列表太长时才启动新副本)。
  • 顺便说一句,虽然这使我们脱离了 POSIX 合规性,转而使用 GNUisms,但人们也可能会考虑从 -exec 切换到 -execdir(除非文件被组织在许多小子目录中);在单个目录中运行wc 意味着不需要在命令行中传递目录名称,从而增加了可以传递给wc 的每个副本的单个文件的数量。
  • @CharlesDuffy 它是 GNU 主义吗? find /some/data/dir/with/text/files/ -type f -print0 | xargs -0 wc -l >report.txt
  • @LéaGris,apparently not。 (2001 年在PASC Interpretation 1003.2 #210 中采用。)
猜你喜欢
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2019-03-25
相关资源
最近更新 更多