参数列表对于 ls 来说太长

参数列表对于 ls 来说太长

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

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

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

答案1

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

这个限制对于二进制程序和内核来说都是安全的。看ARG_MAX,新进程的参数最大长度有关它及其使用和计算方式的更多信息。

管道尺寸没有这样的限制。所以你可以简单地发出这个命令:

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

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

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

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

touch "hello
world"

答案2

这主要取决于你的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 关于包含换行符的文件名的评论。)

答案3

另一个解决方法:

ls | grep -c '\.txt$'

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

您可能想使用:

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

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

并且您应该考虑重新组织文件,这样单个目录中就不会出现太多文件。这可能可行,也可能不可行。

答案4

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

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

相关内容