如何递归地统计一个文件夹中所有代码行数?

2015

我们有一个PHP应用程序,想要计算特定目录及其子目录下所有代码行数。

我们不需要忽略注释,因为我们只是想大致了解代码规模。

wc -l *.php 

该命令对于给定的目录效果很好,但它忽略了子目录。我认为下面的注释可能起作用,但它返回74,显然不是这种情况...

find . -name '*.php' | wc -l

如何正确地语法传递包含所有子目录文件的目录?

51个回答

3220

尝试:

find . -name '*.php' | xargs wc -l

或者(当文件名包含特殊字符,比如空格时)

find . -name '*.php' | sed 's/.*/"&"/' | xargs  wc -l

SLOCCount 工具 也可能有所帮助。

它可以为您指定的任何层次结构提供准确的源代码行数计数,以及一些其他统计信息。

排序输出:

find . -name '*.php' | xargs wc -l | sort -nr


46
可能值得一看的替代 sloccount 工具是 http://cloc.sourceforge.net/(支持更多编程语言,但提供的信息较少)。 - AsTeR
38
包括文件的情况下:find . -name '*.php' -o -name '*.inc' | xargs wc -l。该命令用于计算当前目录及其子目录中所有扩展名为.php或.inc的文件的行数总和。 - rymo
61
如果有多个文件,这将打印出不止一个数字(因为wc将被多次运行)。此外,它不能处理许多特殊的文件名。 - l0b0
52
@idober: find . -name "*.php" -not -path "./tests*" | xargs wc -l这行命令的意思是在当前目录及其子目录中查找所有后缀名为.php的文件,但排除掉路径中包含“./tests*”字符串的文件,然后使用xargs命令将这些文件名传递给wc命令,统计它们的行数。 - endre
26
如果目录名包含空格... 上述命令将失败!! - nitish712
显示剩余28条评论

563
你可以使用cloc工具来实现此目的。它会报告每种语言中的行数以及其中有多少是注释等信息。CLOC可在Linux、Mac和Windows上使用。
使用方法和输出示例:
$ cloc --exclude-lang=DTD,Lua,make,Python .
    2570 text files.
    2200 unique files.
    8654 files ignored.

http://cloc.sourceforge.net v 1.53  T=8.0 s (202.4 files/s, 99198.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                    1506          77848         212000         366495
CSS                             56           9671          20147          87695
HTML                            51           1409            151           7480
XML                              6           3088           1383           6222
-------------------------------------------------------------------------------
SUM:                          1619          92016         233681         467892
-------------------------------------------------------------------------------

17
这是一个很棒的工具,运行速度快,最后提供有用的统计数据。我很喜欢它。 - Rob Forrest
4
请注意,您可以使用cygwin(或其他类似的端口/环境)在Windows上运行Unix命令。对我来说,拥有这种访问权限非常有用,它是必不可少的。Unix命令行是神奇的。我特别喜欢Perl和正则表达式。 - Curtis Yallop
3
您是否考虑编辑此问题的开头,以明确指出 cloc 是跨平台的,因为它只是一个 Perl 脚本? - Kyle Strand
1
非常完美,当然在Windows bash中也可以正常工作。 - yurisnm
2
我没有安装那个工具,但是如果已经安装了Node,你可以运行npx cloc myApp来在不全局安装的情况下运行它。 - Marcus Hammarberg
显示剩余6条评论

563

另一个一行代码解决的方法:

( find ./ -name '*.php' -print0 | xargs -0 cat ) | wc -l

它适用于带有空格的名称并仅输出一个数字。


2
我找到了最好的解决方案。我将路径和文件类型参数化,并将此代码添加到我的路径上的脚本中。我计划经常使用它。 - S.C.
3
@TorbenGundtofte-Bruun - 请查看 man find .. 使用 xargs -0 的 print0 可以让您操作文件名中包含空格或其他奇怪字符的文件。 - Shizzmo
2
@TorbenGundtofte-Bruun - 另外,xargs 中的 -0 对应于 print0,它是一种编码/解码方式来处理空格。 - Tristan Reid
8
如果你需要多个名称过滤器,我发现(至少在 MSYSGit 版本的 find 中),你需要额外加括号:( find . \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 cat ) | wc -l - Zrax
2
在我看来,这应该是被接受的答案,因为它给出了一个单一的数字(正如问题所暗示的)。 - Pithikos
显示剩余14条评论

454
如果您使用的是相当新的Bash版本(或ZSH),那么这将变得更加简单:
wc -l **/*.php
在Bash shell中,这需要设置globstar选项,否则**通配符不会递归。要启用此设置,请输入:
shopt -s globstar

要使这个变化永久生效,将它添加到初始化文件之一(~/.bashrc~/.bash_profile等)中。


11
我为其简洁性点赞,但是我想指出它似乎不能递归地搜索目录,它只检查当前目录的子目录。这是在SL6.3上的情况。 - Godric Seer
10
这取决于您使用的Shell以及设置的选项。要使此功能起作用,Bash要求必须设置 globstar 选项。 - Michael Wild
2
@PeterSenna,使用当前的3.9.8内核档案,命令wc -l **/*.[ch]可以找到总共15195373行。不确定您是否认为这是一个“非常低的值”。再次提醒您需要确保在Bash中启用了globstar。您可以使用shopt globstar进行检查。要显式启用它,请执行shopt -s globstar - Michael Wild
6
这是一个不错的解决方案,但如果你有大量的.php文件,由于 wc 不是内置程序,它仍然会导致ARG_MAX溢出。 - Reinstate Monica Please
2
如果您想包含多个文件类型(通过扩展名),则可以扩展此功能并使用bash扩展:wc -l **/*.{py,yml,md,js,html} - geogeo
显示剩余5条评论

117
在类Unix系统上,有一个名为的工具,它提供了代码统计功能。
我在我们代码库中的一个随机目录上运行它,它显示:
      59 text files.
      56 unique files.
       5 files ignored.

http://cloc.sourceforge.net v 1.53  T=0.5 s (108.0 files/s, 50180.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                               36           3060           1431          16359
C/C++ Header                    16            689            393           3032
make                             1             17              9             54
Teamcenter def                   1             10              0             36
-------------------------------------------------------------------------------
SUM:                            54           3776           1833          19481
-------------------------------------------------------------------------------

2
@moose,从技术上讲,simtao明确提到它作为Windows用户的解决方案,没有提到Linux或Unix。 - Tim Seguine
5
@moose在我的回答之后很久才将表格编辑到他的回答中,现在两者看起来确实很相似。 - Calmarius
我喜欢它。cloc 真的很整洁。但是那个名字是什么意思? - Manoel Vilela
现在它也支持Windows了!假设您已经安装了chocolateychoco install cloc - icc97
@Manoel:我猜它的意思是“统计代码行数”。 - Carl Winbäck

48

您没有指定有多少个文件或所需的输出内容。

这可能是您要找的:

find . -name '*.php' | xargs wc -l

5
只要文件不太多,这个方法就能奏效:如果有很多文件,结果会分成几行(xargs 会将文件列表拆分成几个子列表)。 - Pascal MARTIN
啊,是的。这就是我为什么说他没有指定有多少个文件。我的版本更容易记住,但如果你有超过几个文件,Shin的版本更好。我投赞成票。 - Paweł Polewicz
我需要将这个适应于一个函数的使用,在这里单引号太过限制了:go () { mkdir /tmp/go; [[ -f ./"$1" ]] && mv ./"$1" /tmp/go; (find ./ -type f -name "$*" -print0 | xargs -0 cat ) | wc -l; wc -l /tmp/go/*; mv /tmp/go/* . }结果接近于 *.py 的行数计数,但它不知道 *.js*.html - jalanb

43

又是一个变化 :)

$ find . -name '*.php' | xargs cat | wc -l
这将给出总和,而不是逐个文件的结果。 在“find”后面添加“.”即可实现此功能。

至少在cygwin中,我使用以下命令获得更好的结果:$ find -name \*\.php -print0 | xargs -0 cat | wc -l - Martin Haeberli
在 Darwin 上,这只会给出一个总数:find . -name '*.php' | xargs cat | wc -l ... 而这个会逐个文件列出行数和总行数:find . -name '*.php' | xargs wc -l - OsamaBinLogin

35

使用 find 命令的 -execawk 工具。以下是操作步骤:

find . -type f -exec wc -l {} \; | awk '{ SUM += $0} END { print SUM }'

这个片段查找所有文件(-type f)。要按文件扩展名查找,请使用-name

find . -name '*.py' -exec wc -l '{}' \; | awk '{ SUM += $0; } END { print SUM; }'

2
从功能上讲,这个方法完美无缺,但是在大型列表(Linux源代码)上它非常慢,因为它为每个文件启动一个wc进程,而不是所有文件的1个wc进程。我用这种方法计时为31秒,而使用find . -name '*.c' -print0 |xargs -0 wc -l只需要1.5秒。话虽如此,这种更快的方法(至少在OS X上)最终会多次打印“总计”,因此需要一些额外的过滤才能得到正确的总计(我在我的答案中发布了详细信息)。 - Doug Richardson
这样做的好处是可以处理无限数量的文件。干得好! - ekscrypto
1
这是处理大量GB和文件时更好的解决方案。在一个cat表单上执行一个wc很慢,因为系统必须先处理所有GB才能开始计算行数(使用200GB的jsons、12k个文件进行了测试)。先执行wc然后再计算结果要快得多。 - ulkas
2
@DougRichardson,你考虑一下这个: find . -type f -exec wc -l {} \+ 或者 find . -name '*.py' -type f -exec wc -l {} \+, 它会在输出的末尾打印出总数。如果你只关心总数,可以更进一步使用 tailfind . -type f -exec wc -l {} \+ | tail -1 或者 find . -name '*.py' -type f -exec wc -l {} \+ | tail -1 - JamieJag

31

这个工具 Tokei 可以显示一个目录中代码的统计信息。Tokei会按语言分组展示文件数、代码行数、注释行数和空行数。Tokei也可以在Mac、Linux和Windows上使用。

Tokei输出的示例如下:

$ tokei
-------------------------------------------------------------------------------
 Language            Files        Lines         Code     Comments       Blanks
-------------------------------------------------------------------------------
 CSS                     2           12           12            0            0
 JavaScript              1          435          404            0           31
 JSON                    3          178          178            0            0
 Markdown                1            9            9            0            0
 Rust                   10          408          259           84           65
 TOML                    3           69           41           17           11
 YAML                    1           30           25            0            5
-------------------------------------------------------------------------------
 Total                  21         1141          928          101          112
-------------------------------------------------------------------------------

Tokei可以按照存储库中README文件的说明进行安装。

1
非常好的工具,谢谢。 - Ahmet Ardal
但是如何使用 tokei 递归地计算目录中的代码,这个问题是关于什么的? - user158

28

对我而言,更常见和简单的方法是,假设您需要计算不同名称扩展名(比如本机文件)的文件数量:

wc $(find . -type f | egrep "\.(h|c|cpp|php|cc)" )

6
这并不完全做你想做的事情。 find . -name '.[am]' 和 find . -name '.[a|m]' 是相同的,两者都会找到所有以 .m 或 .a 结尾的文件。 - Omry Yadan
1
但是第二个也会找到以 .| 结尾的文件(如果有的话)。因此,[h|c|cpp|php|cc] 最终与 [hcp|] 相同。 - OsamaBinLogin
反引号已经过时,请使用 $() - Sandburg
这在Cygwin下可以工作。当然,“C:\”驱动器必须遵循cygwin约定,例如:wc $(find /cygdrive/c//SomeWindowsFolderj/ -type f | egrep ".(h|c|cpp|php|cc)" ) - Christian Gingras

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接