目录中的总行数
Posted
技术标签:
【中文标题】目录中的总行数【英文标题】:Total number of lines in a directory 【发布时间】:2018-04-12 02:22:06 【问题描述】:我有一个包含数千个文件的目录(目前为 100K)。当我使用wc -l ./*
时,我会得到:
c1 ./test1.txt
c2 ./test2.txt
...
cn ./testn.txt
c1+c2+...+cn total
因为目录里有很多文件,我只想看总数而不是细节。有什么办法吗?
我尝试了几种方法,但出现以下错误:Argument list too long
【问题讨论】:
快速简单的解决方案可能是ls -l | wc -l
。
@Guest,感谢您的回复。我试过了,它显示的是 n 而不是 c1+c2+...+cn
。
cat * | wc -l
,也许吧?我很确定这是重复的,很难。
@BenjaminW。它适用于目录中的少量文件。我的目录中有很多文件,所以我收到“参数列表太长”的错误
这能回答你的问题吗? How can I count all the lines of code in a directory recursively?
【参考方案1】:
如果你想要的是总行数而不是别的,那么我建议使用以下命令:
cat * | wc -l
这个catenates 包含当前工作目录中所有文件的内容,并将生成的文本块通过wc -l
管道传输。
我觉得这很优雅。请注意,该命令不会产生多余的输出。
更新:
我没有意识到您的目录包含这么多文件。根据这些信息,您应该尝试以下命令:
for file in *; do cat "$file"; done | wc -l
大多数人不知道您可以将for
循环的输出直接通过管道传输到另一个命令中。
请注意,这可能非常慢。如果您有 100,000 个左右的文件,我猜大概需要 10 分钟。这是一个疯狂的猜测,因为它取决于几个我无法检查的参数。
如果你需要更快的东西,你应该用 C 编写你自己的实用程序。如果你使用 pthreads,你可以让它快得惊人。
希望对您有所帮助。
最后一点:
如果您有兴趣构建自定义实用程序,我可以帮助您编写一个代码。这将是一个很好的练习,其他人可能会觉得它很有用。
【讨论】:
唯一的 nit 是cat *
不会捕获隐藏(点)文件。 cat * .[^.]*
将同时获得两者。
@lifecrisis 它适用于目录中的少量文件。我的目录中有很多文件,所以我收到“参数列表太长”的错误
@DavidC.Rankin,如果问题要求包含点文件,这将很有用。请注意,您应该将模式 ..?*
添加到您的命令中。就目前而言,您的模式将与 ..file
等文件不匹配。
当您在 S.O. 上回答问题时,您就进入了老师的名单。更好的答案将解释答案的细微差别以及一种方法与另一种方法相比的潜在缺点。这有利于学习。虽然问题没有明确要求点文件,但也没有明确排除它们。正如所写,您的答案是对如何对目录中所有文件中的行求和的部分答案。
@lifecrisis 感谢您提供完整的解释和更新。系统关闭了几天。我会在它开始工作时尝试它并通知您。【参考方案2】:
awk 'END print NR" total"' ./*
将是一个有趣的比较,以找出有多少行不以新行结尾。
结合 awk 和 Gordon 的 find 解决方案并避免使用“.”文件。
find ./* -maxdepth 0 -type f -exec awk ‘END print NR’ +
不知道这是好是坏,但它确实给出了更准确的计数(对我而言)并且不计算“。”中的行数文件。使用 ./* 只是一个似乎可行的猜测。
仍然需要深度,./* 需要“0”深度。
我确实使用“cat”和“awk”解决方案(使用相同的查找)得到了相同的结果,因为“cat *”处理了新行问题。我没有包含足够文件的目录来测量时间。有趣的是,我喜欢“猫”解决方案。
【讨论】:
很多方法可以做到这一点......首先想到的是在你的 wc 上使用“tail - 1”或“grep total”,第二个想法是 awk 会更准确,因为 wc 只计算行数以换行符结尾。 很多地方都是重复的。有许多不同的方法可以做到这一点。我发现 awk 解决方案比我的桌面目录中的任何 wc 解决方案多六行。 @Gordon Davission:我试过了,但出现以下错误:“参数列表太长” 听起来你需要一个脚本来遍历所有文件。命令行只能做这么多。有多少个文件? 目前为 100K,但可能更多【参考方案3】:Credit:这建立在@lifecrisis 的答案之上,并将其扩展为处理 large 数量的文件:
find . -maxdepth 1 -type f -exec cat + | wc -l
find
将查找当前目录中的所有文件,将它们分成可以作为参数传递的最大组,然后在组上运行cat
。
【讨论】:
Davission,你能简单解释一下吗?什么是 ”。”?是指在当前目录中搜索吗? @Shabnam 是的,“。”指当前目录。见"Regarding the Single and the Double Dot within Directories"。 我给这个竖起大拇指。它非常快,并且比我上面建议的for
循环更好地处理负载。我也没有意识到find
会为您将文件分组。这是一件好事!
@lifecrisis 是的,这是find
的一个方便的功能。请注意,-exec cmd +
将批量运行文件,而-exec cmd \;
将一次运行一个文件。 +
的行为与 xargs
非常相似。
@GordonDavisson 感谢您的解释。系统关闭了几天。我会在它开始工作时尝试它并通知您【参考方案4】:
(很抱歉将其添加为答案 - 但我没有足够的评论声誉。)
对@lifecrisis 回答的评论。也许cat
正在放慢速度。我们可以将 cat 替换为 wc -l
,然后使用 awk
来添加数字。 (这可能会更快,因为需要通过管道的数据要少得多。)
那是
for file in *; do wc -l "$file"; done | awk 'sum += $1 END print sum'
而不是
for file in *; do cat "$file"; done | wc -l
(免责声明:我没有在其他答案中加入许多改进,但我认为这一点足够有效,可以写下来。)
这是我的比较结果(我首先运行了较新的版本,以便任何缓存效果都会对较新的候选者产生不利影响)。
$ time for f in `seq 1 1500`; do head -c 5M </dev/urandom >myfile-$f |sed -e 's/\(................\)/\1\n/g'; done
real 0m50.360s
user 0m4.040s
sys 0m49.489s
$ time for file in myfile-*; do wc -l "$file"; done | awk 'sum += $1 END print sum'
30714902
real 0m3.455s
user 0m2.093s
sys 0m1.515s
$ time for file in myfile-*; do cat "$file"; done | wc -l
30714902
real 0m4.481s
user 0m2.544s
sys 0m4.312s
【讨论】:
【参考方案5】:如果您只想知道目录中的总行数,不包括总行数
ls -ltr | sed -n '/total/!p' | awk 'print NR'
上一条评论将给出总行数,其中仅包括所有文件中的行数
【讨论】:
【参考方案6】:以下命令将提供路径中所有文件的总行数
for i in `ls- ltr | awk ‘$1~”^-rw”print $9’`; do wc -l $I | awk ‘print $1’; done >>/var/tmp/filelinescount.txt
Cat /var/tmp/filelinescount.txt| sed -r “s/\s+//g”|tr “\n” “+”| sed “s:+$::g”| sed ’s/^/“/g’| sed ’s/$/“/g’ | awk ‘print “echo” “ “ $0”+bc”’| sh
【讨论】:
【参考方案7】:这将为您提供当前目录中所有文件(包括隐藏文件)的总数:
$ find . -maxdepth 1 -type f | xargs wc -l | grep total
1052 total
要计算不包括隐藏文件的文件,请使用:
find . -maxdepth 1 -type f -not -path "*/\.*" | xargs wc -l | grep total
【讨论】:
如果我不想要隐藏文件的信息,如何编辑这一行? @Shabnam:然后使用-not -path "*/\.*"
排除当前目录中的隐藏文件。检查更新的答案以上是关于目录中的总行数的主要内容,如果未能解决你的问题,请参考以下文章