我的文件夹中有 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-from
GNU 选项: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 将空格转换为 +),然后通过管道传输以执行计算。wc
sh
find ... -exec
awk
find
+
bc
就像$d
sed 脚本中的 一样,$1
awk 脚本中的 也因为双引号的原因需要转义。
答案3
如果您有太多文件,您可能不希望将信息发送到标准输出,因此您可以执行以下操作:
IFS="\n"; for file in find ./ -type f; do wc -l "$file" >> ~/linecount.txt; done