/bin/cat:参数列表太长

/bin/cat:参数列表太长

我的文件夹中有 119766 个文件。它们是 CSV 文件。我想找出所有文件的总行数。

我正在尝试运行以下命令:

cat * |wc -l

但出现以下错误:

-bash: /bin/cat: 参数列表太长

我怎样才能做到这一点?有没有办法解决?

我想补充的一件事是,总行数会非常大。

答案1

好吧,为了给cat这个问题一个新的家,应该这样做:

find . -type f -exec cat {} + | wc -l

它一次又一次地执行cat具有最大可接受数量的文件名的 a( ) 并将所有内容通过管道传输到.如果不想遍历子目录,则必须在 find 命令中的目录后面添加 a 。+wc-maxdepth 1

作为替代方案,可以使用--files0-fromGNU 选项:wc

find . -type f -print0 | wc -l --files0-from=- | tail -1

该选项使wc读取的不是内容而是文件名来自标准输入,以空字符分隔。使用-print0,find将打印这些以空字节分隔的文件名。由于wc仍会打印每个文件的行数,因此建议跳过除末尾的摘要行之外的所有内容,因此tail.

这两种解决方案都有一个优点,即它们可以在任何语言环境中工作,而 @cas 的解决方案必须进行调整(例如,“total”在德语中是“insgesamt”)。

答案2

如果您想要每个单独文件的行数:

find . -type f -exec wc -l {} + | awk '! /^[ 0-9]+[[:space:]]+total$/'

我已经排除了总行数,因为其中有几行正在处理这么多文件。将find ... -exec ... +尝试将尽可能多的文件名放入单个命令行中,但这将比 119766 个文件少很多....每次调用可能只有几千个(最多)wc,并且每个文件都会产生自己的结果独立的“总”线。

如果您想要合并所有文件中的总行数,这是一种方法:

find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc

这仅打印总行数上的行数,将其通过管道传输xargs以获取一行上的所有计数,然后 sed 将空格转换为+符号,然后将大量数据通过管道传输以bc进行计算。

输出示例:

$ cd /usr/share/doc
$ find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc 
53358931

更新2022-05-05

最好wc -l通过运行sh。这避免了调用任何文件名时出现问题的风险total......除了总行是输出的最后一行之外wc,没有办法区分实际的总行与名为“的文件的输出” Total”,因此匹配“total”的简单 awk 脚本无法可靠地工作。

要显示单个文件的计数(不包括总数):

find . -type f -exec sh -c 'wc -l "$@" | sed "\$d"' sh {} +

wc -l对所有文件名运行,并从 运行的每个批处理中删除最后一行(“总”行)-exec

sed 脚本中的$d需要转义,因为该脚本位于双引号字符串中,而不是更常见的单引号字符串中。使用双引号是因为整个sh -c是单引号字符串。转义一个$符号比'\''在单引号中伪造嵌入单引号更容易且更具可读性。

仅显示总数:

find . -type f -exec sh -c 'wc -l "$@" | awk "END {print \$1}"' sh {} + |
  xargs | sed -e 's/ /+/g' | bc

它不是用来删除传递给via by 的sed每批文件中的最后一行,而是只打印每批中的最后一行(“总计”)。然后,的输出被转换为单行 (xargs),每个数字之间有字符(sed 将空格转换为 +),然后通过管道传输以执行计算。wcshfind ... -execawkfind+bc

就像$dsed 脚本中的 一样,$1awk 脚本中的 也因为双引号的原因需要转义。

答案3

如果您有太多文件,您可能不希望将信息发送到标准输出,因此您可以执行以下操作:

IFS="\n"; for file in find ./ -type f; do wc -l "$file" >> ~/linecount.txt; done

相关内容