如何递归计算目录中的所有代码行?


1620

我们有一个PHP应用程序,并希望计算特定目录及其子目录下的所有代码行。我们不需要忽略评论,因为我们只是想获得一个大概的想法。

wc -l *.php 

该命令在给定目录中效果很好,但是会忽略子目录。我以为这可能行得通,但返回74,绝对不是这种情况...

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

送入所有文件的正确语法是什么?

Answers:


2647

尝试:

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

SLOCCount工具也可能会有所帮助。

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

排序输出:

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


31
cloc.sourceforge.net可能值得寻找sloccount的替代品(更多语言但更少信息)
AsTeR 2012年

31
包含文件还包括:find . -name '*.php' -o -name '*.inc' | xargs wc -l
rymo

52
当有许多文件时,这将打印多个数字(因为wc将多次运行。也不处理许多特殊文件名。)
l0b0 2013年

42
@idober:find . -name "*.php" -not -path "./tests*" | xargs wc -l
endre

19
如果目录名包含空格,则上述命令将失败!
nitish712 2014年

474

对于另一种班轮:

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

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


1
+1同上...永远搜索...所有其他“查找”命令仅返回实际文件的数量.... -print0的东西在这里为我得到了实际的行数!!!谢谢!
Ronedog

3
@ TorbenGundtofte-Bruun-参见man find..具有xargs -0的print0,可让您处理名称中包含空格或其他怪异字符的文件
Shizzmo 2014年

2
@ TorbenGundtofte-Bruun-同样,xargs中的-0对应于print0,它是一种编码/解码,用于处理空格。
Tristan Reid 2014年

7
如果您需要多个名称过滤器,我发现(至少使用find的MSYSGit版本),需要额外的括号: ( find . \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 cat ) | wc -l
Zrax 2014年

1
@DesignbyAdrian:日志记录有助于崩溃恢复,而不是速度。由于缓存或非常快的HDD,您可能会看到良好的性能。
jmh 2015年

398

如果使用最新版本的Bash(或ZSH),则要简单得多:

wc -l **/*.php

在Bash shell中,这需要设置globstar选项,否则**glob-operator不会递归。要启用此设置,请发出

shopt -s globstar

为了使这个永久性的,它添加到初始化文件之一(~/.bashrc~/.bash_profile等等)。


7
为了简单起见,我对此表示赞同,但是我只想指出,它似乎不是递归搜索目录,它仅检查当前目录的子目录。这是在SL6.3上。
Godric Seer 2013年

7
这取决于您的外壳和设置的选项。需要globstar设置 Bash 才能起作用。
Michael Wild

2
@PeterSenna,使用当前的3.9.8内核归档文件,该命令wc -l **/*.[ch]总共找到15195373行。不知道您是否认为这是“非常低的价值”。同样,您需要确保已globstar在Bash中启用。您可以通过进行确认shopt globstar。要明确启用它,请执行shopt -s globstar
Michael Wild

5
@MichaelWild这是一个很好的解决方案,但是ARG_MAX如果您有大量.php文件,它仍然会溢出,因为wc它不是内置的。
恢复莫妮卡

1
@AlbertSamuel不,您需要比较两种方法产生的文件列表。如@BroSlow所述,我的方法存在无法处理大量文件的问题。如果由产生的路径find包含空格,则可接受的答案将失败。这可以通过分别使用print0--nullfindxargs调用来解决。
Michael Wild

363

您可以使用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
-------------------------------------------------------------------------------

4
这是一个非常可爱的工具,可以很好地运行,并在最后迅速提供有用的统计数据。爱它。
罗伯·福雷斯特

4
请注意,您可以使用cygwin(或其他类似的端口/环境)在Windows上运行Unix命令。对我来说,这种访问非常有用,这是必要的。Unix命令行非常神奇。我特别喜欢perl和正则表达式。
柯蒂斯·雅洛普

CLOC和SLOCCount在2015年中的Macbook上运行良好。请注意,对于127k Java Android项目,它们的数量接近但并不完全相同。还要注意,与iOS相当的是LoC的2倍;因此,SLOCCount中的“费用”指标可能已关闭(或者iOS开发人员的
收入

2
您是否考虑编辑此问题的开头以明确说明它cloc是跨平台的,因为它只是一个Perl脚本?
凯尔·斯特兰德

完美,当然也可以在Windows bash中正常工作。
yurisnm '19

100

在类似UNIX的系统上,有一个称为的工具cloc可提供代码统计信息。

我在我们的代码库中的一个随机目录中遇到了这样的情况:

      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 2015年

5
@moose Table的编辑时间比我的回答晚很多,现在两者确实看起来很相似。
Calmarius 2015年

我喜欢。cloc真的很整洁。但是这个名字叫什么意思呢?
Manoel Vilela'7

现在也在Windows上!假设您有巧克力choco install cloc

35

您没有指定有多少文件或所需的输出是什么。这是你想要的:

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

2
只要没有太多文件,这将起作用:如果文件太多,结果将得到几行(xargs会将文件列表拆分为几个子列表)
Pascal MARTIN

是的。这就是为什么我说他没有指定有多少文件的原因。我的版本更容易记住,但如果您拥有多个文件,Shin的版本会更好。我投票赞成。
帕维尔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/* . } 结果接近slocount的*.py,但它不知道*.js*.html
jalanb '16

31

还有另一种变化:)

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

编辑:这将给出总计,而不是逐个文件。

Edit2:添加.find使其生效


这两个答案总和。
josh123a123 2014年

至少在cygwin中,我得到了更好的结果:$ find -name \*\.php -print0 | xargs -0 cat | wc -l
Martin Haeberli 2014年

在达尔文市,这只是一个总计:find . -name '*.php' | xargs cat | wc -l...而这给出了逐个文件和总计:find . -name '*.php' | xargs wc -l
OsamaBinLogin

30

令人惊讶的是,没有基于find -exec和的答案awk。开始了:

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秒,而使用则为1.5秒find . -name '*.c' -print0 |xargs -0 wc -l。就是说,这种更快的方法(至少在OS X上是这样),最终会多次打印“总计”,因此需要进行一些额外的过滤才能获得适当的总计(我在答案中发布了详细信息)。
道格·理查森

这具有处理无限数量的文件的好处。做得好!
ekscrypto '16

1
一旦处理大量GB和文件,这将是更好的解决方案。做一个wc的窗体上cat是缓慢的,因为系统首先必须处理所有GB开始计数线(与jsons的200GB,12K文件测试)。做wc第一,然后计算结果是远远快
ulkas

1
@DougRichardson,您可以考虑使用此方法:find . -type f -exec wc -l {} \+find . -name '*.py' -type f -exec wc -l {} \+ 在输出末尾打印总计。如果您tailfind . -type f -exec wc -l {} \+ | tail -1find . -name '*.py' -type f -exec wc -l {} \+ | tail -1
只想

25

就我而言,更常见和更简单,假设您需要计算不同名称扩展名的文件(例如,本地文件)

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

感谢您的反馈,我已对其进行了更正。


6
这并不完全符合您的想法。找 。-name' 。[am]'与find相同。-name'。[a | m]'都将找到所有以.m或.a结尾的文件
Omry Yadan 2013年

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

21

POSIX

与这里的大多数其他答案不同,它们可以在任何POSIX系统上工作,适用于任何数量的文件,并具有任何文件名(除非另有说明)。


每个文件中的行:

find . -name '*.php' -type f -exec wc -l {} \;
# faster, but includes total at end if there are multiple files
find . -name '*.php' -type f -exec wc -l {} +

每个文件中的行,按文件路径排序

find . -name '*.php' -type f | sort | xargs -L1 wc -l
# for files with spaces or newlines, use the non-standard sort -z
find . -name '*.php' -type f -print0 | sort -z | xargs -0 -L1 wc -l

每个文件中的行,按行数排序,降序

find . -name '*.php' -type f -exec wc -l {} \; | sort -nr
# faster, but includes total at end if there are multiple files
find . -name '*.php' -type f -exec wc -l {} + | sort -nr

所有文件中的行总数

find . -name '*.php' -type f -exec cat {} + | wc -l

19

有一个名为sloccount的小工具可以对目录中的代码行进行计数。应该注意的是,它会做很多事情,因为它会忽略空行/注释,按照每种编程语言对结果进行分组并计算一些统计信息。


对于Windows,LocMetrics可以完成工作
Camille

15

您想要的是一个简单的for循环:

total_count=0
for file in $(find . -name *.php -print)
do
    count=$(wc -l $file)
    let total_count+=count
done
echo "$total_count"

3
与建议的答案相比,这不是过度杀伤力xargs吗?
内森·费尔曼

5
不,内森 xargs答案不一定会将计数打印为单个数字。它可能只打印一堆小计。
罗伯·肯尼迪

3
如果文件名包含空格,该程序将如何处理?那换行呢?;-)
帕维尔Polewicz

38
如果您的文件名包含换行符,那么我想您会遇到更大的问题。
卡扎伊2012年

2
@ennuikiller与此相关的问题很多,首先,它会在带有空格的文件上中断。IFS=$'\n'在循环之前进行设置至少会解决所有文件名中带有换行符的问题,但文件除外。其次,您没有引用'*.php',因此它将由shell而不是not扩展,因此findergo实际上不会在子目录中找到任何php文件。也是-print多余的,因为它暗示着没有其他动作。
恢复莫妮卡


11

一个简单而快速的文件,将使用的所有搜索/过滤功能find,当文件太多(数字参数溢出)时不会失败,对于名称中带有有趣符号的文件可以正常使用,而无需使用xargs,则不会启动无益地高数量的外部命令的(由于+find-exec)。干得好:

find . -name '*.php' -type f -exec cat -- {} + | wc -l

2
我本人将要发布此变量的变体(\;而不是+因为我不知道该变量而已),所以此答案应该是正确的答案。
Mark K Cowan

7

我知道这个问题被标记为 ,但似乎您要解决的问题也与PHP有关。

塞巴斯蒂安·伯格曼(Sebastian Bergmann)编写了一个名为PHPLOC的工具,该工具可以满足您的需求,并且可以为您提供项目复杂性的概述。这是其报告的示例:

Size
  Lines of Code (LOC)                            29047
  Comment Lines of Code (CLOC)                   14022 (48.27%)
  Non-Comment Lines of Code (NCLOC)              15025 (51.73%)
  Logical Lines of Code (LLOC)                    3484 (11.99%)
    Classes                                       3314 (95.12%)
      Average Class Length                          29
      Average Method Length                          4
    Functions                                      153 (4.39%)
      Average Function Length                        1
    Not in classes or functions                     17 (0.49%)

Complexity
  Cyclomatic Complexity / LLOC                    0.51
  Cyclomatic Complexity / Number of Methods       3.37

如您所见,从开发人员的角度来看,所提供的信息要有用得多,因为它可以粗略地告诉您项目在开始使用之前的复杂程度。


7

猜测没有人会发现这个隐藏在后面...然而,到目前为止,没有答案能解决文件名带有空格的问题。此外,xargs如果树中路径的总长度超过外壳环境大小限制(在Linux中默认为几兆字节),所有使用都会失败。这是一种可以直接解决这些问题的方法。子外壳会处理带空格的文件。在awk总计单个文件的流wc输出,所以永远不能让空间用完。它还将仅限exec于文件(跳过目录):

find . -type f -name '*.php' -exec bash -c 'wc -l "$0"' {} \; | awk '{s+=$1} END {print s}' 

6

WC -L吗?更好地使用GREP -C ^

wc -l 错误! wc命令计算新行代码,而不是行!如果文件中的最后一行不以新行代码结尾,则不会计算在内!

如果您仍要计数行,请使用 grep -c ^,完整示例:

#this example prints line count for all found files
total=0
find /path -type f -name "*.php" | while read FILE; do
     #you see use grep instead wc ! for properly counting
     count=$(grep -c ^ < "$FILE")
     echo "$FILE has $count lines"
     let total=total+count #in bash, you can convert this for another shell
done
echo TOTAL LINES COUNTED:  $total

最后,提防wc -l陷阱 (计数输入,而不是行!!!)


请阅读POSIX定义的一行。随着grep -c ^你数数不完整的线,这种不完整的线不能出现在一个文本文件中
gniourf_gniourf 2015年

2
我知道。实际上,只有最后一行可能是不完整的,因为它没有EOL。想法正在计算所有行,包括不完整的行。这是很常见的错误,只计算完整的行。数完之后,我们在思考“为什么我错过了最后一行???”。这就是回答的原因,并指出如何正确地做。
Znik

或者,如果您想要一个班轮:find -type f -name '*.php' -print0 | xargs -0 grep -ch ^ | paste -sd+ - | bc 请参阅此处,了解其他替代方案bcstackoverflow.com/q/926069/2400328
techniao

5

使用zsh glob非常简单:

wc -l ./**/*.php

如果您正在使用bash,则只需升级。绝对没有理由使用bash。


4

很简单

find /path -type f -name "*.php" | while read FILE
do
    count=$(wc -l < $FILE)
    echo "$FILE has $count lines"
done

1
如果有一个空间或在文件名中的一个新行会失败
帕维尔Polewicz

4

如果要按行数对结果进行排序,则可以在第一个答案中添加| sort| sort -r-r按降序排列),如下所示:

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

1
由于的输出xargs wc -l是数字,因此实际上需要使用sort -nsort -nr
达斯汀·英格拉姆

4

对于Windows,简便快捷的工具是LocMetrics


如果他们使用bash,则OP不太可能在Windows上运行。

1
@VanessaMcHale问题标题和描述都没有明确要求仅使用unix的解决方案。因此,基于Windows的解决方案是可以接受的。当我在寻找类似的解决方案时,Google也会将我指向该页面。
沃尔夫

此评论对我有所帮助。我试过了,效果很好。
Allan F

4

有些不同:

wc -l `tree -if --noreport | grep -e'\.php$'`

这样做很正常,但是您需要*.php在当前文件夹中至少包含一个文件或其子文件夹之一,否则会wc停滞


也可能会溢出ARG_MAX
马克·科

4

如果您使用的是Linux(我同意),则建议使用工具polyglot。这是明显快于任一sloccountcloc它比更多的其他功能sloccount

您可以使用

poly .

要么

poly

因此,它比一些复杂的bash脚本更加人性化。


4

工具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
-------------------------------------------------------------------------------

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


1
这应该是公认的答案
Elijas

3

如果仅需要PHP中的总行数,那么即使安装了GnuWin32,即使在Windows下,也可以使用非常简单的一行命令。像这样:

cat `/gnuwin32/bin/find.exe . -name *.php` | wc -l

您需要指定find.exe的确切位置,否则将执行Windows提供的FIND.EXE(来自类似于DOS的旧命令),因为它可能在环境PATH中的GnuWin32之前,并且具有不同的参数和结果。

请注意,在上面的命令中,应使用反引号,而不是单引号。


在上面的示例中,我在Windows上使用bash而不是cmd.exe,这就是为什么存在正斜杠“ /”而不是反斜杠“ \”的原因。
Neven Boyanov 2011年

3

首先给出最长的文件(例如,这些长文件可能需要重构爱吗?),并排除一些供应商目录:

 find . -name '*.php' | xargs wc -l | sort -nr | egrep -v "libs|tmp|tests|vendor" | less

3

如果要保持简单,请切开中间人,然后wc使用所有文件名进行调用:

wc -l `find . -name "*.php"`

或使用现代语法:

wc -l $(find . -name "*.php")

只要任何目录名称或文件名中都没有空格,就可以使用。而且,只要您没有成千上万个文件(现代shell支持很长的命令行)即可。您的项目有74个文件,因此您有足够的增长空间。


我喜欢这一个!如果您在混合C / C ++环境中:wc -l `find . -type f \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -print`
Bram

感到惊讶的是,这不是最佳答案
ms4720 '18

3

您不需要所有这些复杂且难以记住的命令。您只需要一个名为line-counter的工具。

快速概述

这就是您获得工具的方式

$ pip install line-counter

使用line命令来获取当前目录下的文件数和行数(递归)

$ line
Search in /Users/Morgan/Documents/Example/
file count: 4
line count: 839

如果您想了解更多细节,请使用line -d

$ line -d
Search in /Users/Morgan/Documents/Example/
Dir A/file C.c                                             72
Dir A/file D.py                                           268
file A.py                                                 467
file B.c                                                   32
file count: 4
line count: 839

这个工具最好的部分是,您可以向其中添加.gitignore配置文件。您可以设置规则以选择或忽略要计数的文件种类,就像在'.gitignore'中所做的一样。

更多描述和用法在这里:https : //github.com/MorganZhang100/line-counter


3

如果文件太多,最好只查找总行数。

find . -name '*.php' | xargs wc -l | grep -i ' total' | awk '{print $1}'

2

至少在OS X上,其他一些答案中列出的find + xarg + wc命令在大型列表中多次打印“总计”,并且没有给出完整的总计。我可以使用以下命令获得.c文件的总计:

find . -name '*.c' -print0 |xargs -0 wc -l|grep -v total|awk '{ sum += $1; } END { print "SUM: " sum; }'

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.