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 似乎是一个内核参数。使用find
andxargs
是解决此限制的典型组合,但我不确定它是否适用于wc
.
将输出通过管道传输find . -name \*\.txt
到文件并计算该文件中的行数应该作为解决方法。