参数列表对于ls而言太长


48

尝试访问ls *.txt | wc -l包含许多文件的目录时出现以下错误:

-bash: /bin/ls: Argument list too long

此“参数列表”的阈值是否取决于发行版或计算机规格?通常,我wc -l会将如此大结果的结果传递给其他一些命令(例如),因此我不关心终端的限制。


6
这被视为解析ls输出,这是一个坏主意,因此最好避免使用它。有关计数的信息,请参见计算目录中文件数量的最佳方法是什么?,有关棘手的解决方法,请参见为什么for循环不会引发“参数过长”错误?
manatwork'5

@manatwork是的,我也看到了这些问题。只是想知道一种更通用的方式使用或重定向命令的长输出的更好方法。

您可以使用getconf ARG_MAX来获取大多数基于Unix的系统的限制
Prasanth 2015年

Answers:


49

你的错误信息参数列表太长来自*ls *.txt

对于二进制程序和您的内核,此限制都是安全的。您将在此页面上看到有关它的更多信息,以及如何使用和计算它。

管道尺寸没有这种限制。因此,您可以简单地发出以下命令:

find -type f -name '*.txt'  | wc -l

注意:在现代Linux上,文件名中的怪异字符(如换行符)将使用ls或这类工具进行转义find,但仍从*显示。如果您使用的是旧版Unix,则需要此命令

find -type f -name '*.txt' -exec echo \;  | wc -l

NB2:我想知道如何创建一个名称中带有换行符的文件。一旦知道了窍门,它并不难:

touch "hello
world"

1
我对它进行了少许修改,以解决其中包含带换行符的文件名的情况。-maxdepth 1如果您不打算计算子目录中的文件,则可能还需要添加一个。
肖恩·高夫

您不需要-exec echo \;
Mikel

@ ShawnJ.Goff我已经测试过了。当前版本的GNU find中不需要`echo`
Coren

@Coren @Mikel-不是每个人都有GNU的find。将find在OS X和基于busybox的系统,和我猜想的任何基于BSD的系统显示,在这一个换行符,这会惹计数的文件名。
肖恩·高夫

?? wc -l正在计算换行符。因此,我们希望它具有换行符。
Mikel

11

它主要取决于您的Linux内核版本。

您应该能够通过运行查看系统的限制

getconf ARG_MAX

它告诉您命令行被shell扩展后可以具有的最大字节数。

在Linux <2.6.23中,限制通常为128 KB。

在Linux> = 2.6.25中,限制为128 KB或堆栈大小的1/4(请参阅ulimit -s参考资料),以较大者为准。

有关所有详细信息,请参见execve(2)手册页


不幸的是,管道ls *.txt无法解决问题,因为限制是在操作系统中,而不是外壳中。

Shell展开*.txt,然后尝试调用

exec("ls", "a.txt", "b.txt", ...)

而且您匹配的文件太多*.txt,超出了128 KB的限制。

您必须做类似的事情

find . -maxdepth 1 -name "*.txt" | wc -l

代替。

(并参阅下面的Shawn J. Goff关于包含换行符的文件名的评论。)


抱歉,您无法提交答案。需要更多的声誉。:(谢谢大家!

您能解释一下最后一行的.-maxdepth 1意思吗?谢谢!:D
GuilhermeSalomé17年

2
@GuilhermeSalomé .表示当前目录,-maxdepth 1表示它不在子目录中。目的是与匹配相同的文件*.txt
Mikel

9

另一个解决方法:

ls | grep -c '\.txt$'

即使ls产生的输出多于ls *.txt产生(或尝试产生)的输出,它也不会遇到“参数过长”的问题,因为您没有将任何参数传递给ls。请注意,grep它采用正则表达式而不是文件匹配模式。

您可能要使用:

ls -U | grep -c '\.txt$'

(假设您的ls支持版本支持此选项)。这告诉您ls不要对输出进行排序,这样可以节省时间和内存-在这种情况下,顺序无关紧要,因为您只是在计数文件。排序输出所花费的资源通常并不重要,但是在这种情况下,我们已经知道您有很多*.txt文件。

而且,您应该考虑重新组织文件,以使单个目录中没有太多文件。这可能可行,也可能不可行。


1

MAX_ARG_PAGES似乎是内核参数。使用findxargs是解决此限制的典型组合,但我不确定它是否适用wc

将输出的find . -name \*\.txt文件发送到文件中并计算该文件中的行数应作为解决方法。


您可以使用ls的输出执行任何操作,但无法解决此问题。只要* .txt通配符超出限制,在启动ls和生成任何输出之前都将失败。
manatwork

是的,我已经更新了答案。
布拉姆

更好。但是要替换它,ls您应该指定-maxdepth 1避免递归扫描子目录。
manatwork'5

抱歉,您无法提交答案。需要更多的声誉。:(

0

这可能很脏,但是可以满足我的需求,并且在我的能力范围内。我认为它的执行速度不是很快,但是可以让我继续前进。

ls | grep jpg | <something>

我得到了90,000长的jpg列表,并将它们通过管道传输到avconv以生成游戏中时光倒流。

我以前使用的是* .jpg | 在遇到此问题之前,请先使用avconv。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.