关于bash:如何递归地计算目录中的所有代码行?

How to count all the lines of code in a directory recursively?

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

1
wc -l *.php

该命令在给定的目录中非常有效,但忽略了子目录。我原以为这可能行得通,但现在是74,这绝对不是事实…

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

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


尝试:

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

SlocCount工具也可能有帮助。

它将为任何您指向的层次结构,以及一些附加的统计信息。


对于另一个内衬:

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

使用带空格的名称,只输出一个数字。


如果使用的是bash(或zsh)的最新版本,就简单多了:

1
wc -l **/*.php

在bash shell中,这要求设置globstar选项,否则**glob运算符不是递归的。要启用此设置,请发出

1
shopt -s globstar

要使其永久化,请将其添加到其中一个初始化文件(~/.bashrc~/.bash_profile等)中。


您可以使用cloc实用程序,它是为这个确切目的而构建的。它报告每种语言中每行的数量,以及其中有多少行是注释等。CLOC在Linux、Mac和Windows上可用。

用法和输出示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ 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
-------------------------------------------------------------------------------


在类Unix系统上,有一个名为cloc的工具,它提供代码统计信息。

我在我们的代码库中的一个随机目录中运行它说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
      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
-------------------------------------------------------------------------------


您没有指定有多少个文件,或者所需的输出是什么。这就是你要找的:

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


还有另一个变种:)

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

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

edit2:find后加.使之工作


POSIX

与这里的大多数答案不同,这些答案适用于任何POSIX系统、任何数量的文件以及任何文件名(除非另有说明)。

每个文件中的行:

1
2
3
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 {} +

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

1
2
3
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

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

1
2
3
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

所有文件中的总行数

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

对于我来说,更常见和简单的是,假设您需要计算不同名称扩展名的文件(也就是本地文件)。

1
wc `find . -name '*.[h|c|cpp|php|cc]'`


令人惊讶的是,基于find的-execawk,没有答案。我们走到这里:

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

此代码段用于查找所有文件(-type f)。要通过文件扩展名查找,请使用-name

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


有一个叫做sloccount的小工具来计算目录中的代码行数。应该注意的是,它做的比您想要的要多,因为它忽略空行/注释,按编程语言对结果进行分组,并计算一些统计数据。


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

1
2
3
4
5
6
7
total_count=0
for file in $(find . -name *.php -print)
do
    count=$(wc -l $file)
    let total_count+=count
done
echo"$total_count"


仅限来源:

1
wc `find`

要过滤,只需使用grep

1
wc `find | grep .php$`

一个简单易行、速度快、使用find的所有搜索/过滤功能,在文件太多时不会失败(数字参数溢出),在文件名中使用有趣符号的文件时,如果不使用xargs,将不会启动无用的大量外部命令(由于+)。〔3〕的-exec。干得好:

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


Guessing no one will ever see this buried at the back... Yet none of the answers so far gets at the problem of filenames with spaces. Additionally, all that use xargs are subject to fail if total length of paths in the tree exceeds the shell environment size limit (defaults to a few megabytes in Linux). Here is one that fixes these problems in a pretty direct manner. The subshell takes care of files with spaces. The awk totals the stream of individual file wc outputs, so ought never to run out of space. It also restricts the exec to files only (skipping directories):

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

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

SebastianBergmann编写了一个名为phploc的工具,它可以满足您的需求,并在此基础上为您提供项目复杂性的概述。这是其报告的一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

正如您所看到的,从开发人员的角度来看,所提供的信息更加有用,因为在您开始使用项目之前,它可以大致告诉您项目有多复杂。


WC -L ? better use GREP -C ^

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

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

1
2
3
4
5
6
7
8
9
#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陷阱(计数进入,而不是线!!!!)


如果要按行数排序结果,可以将| sort| sort -r(-r)添加到第一个答案中,如下所示:

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


使用zsh globs非常简单:

1
wc -l ./**/*.php

如果您使用的是bash,那么只需升级即可。完全没有理由使用bash。


不同的东西:

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

这很好,但您需要在当前文件夹或其子文件夹中至少有一个*.php文件,否则wc暂停。


如果您只需要输入总行数,比如说您的PHP文件,那么即使在安装了gnuwin32的Windows下,也可以使用非常简单的单行命令。这样地:

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

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

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


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

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

对于Windows,简单快速的工具是loctmetrics。


如果你在Linux上(我认为你是),我推荐我的工具polyglot。它比sloccountcloc快得多,而且比sloccount更具特色。

你可以用

1
poly .

1
poly

因此,它比一些复杂的bash脚本更加用户友好。


你不需要所有这些复杂而难以记忆的命令。你只需要一个叫做线路计数器的工具。

快速概述

这就是你得到工具的方法

1
$ pip install line-counter

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

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

如果您需要更多的细节,只需使用line -d

1
2
3
4
5
6
7
8
$ 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


不包括空行

1
2
find . -name"*.php" | xargs grep -v -c '^$' | awk 'BEGIN {FS=":
<div class="suo-content">[collapse title=""]<ul><li>不起作用。.</li></ul>[/collapse]</div><hr><P>至少在OSX上,在一些其他答案中列出的find+xarg+wc命令在大型列表中多次打印"total",并且没有给出完整的total。我可以使用以下命令获得.c文件的单个总数:</P><P><wyn>find . -name '
*.c' -print0 |xargs -0 wc -l|grep -v total|awk '{ sum += $1; } END { print"SUM:" sum; }'</wyn></P><hr><P>虽然我喜欢这些脚本,但我更喜欢这一个,因为它还显示每个文件的摘要,以及总计</P>[cc lang="bash"]wc -l `find . -name"*.php"`

我使用了这个从SRC项目目录启动的内联脚本:

1
 for i in $(find . -type f); do rowline=$(wc -l $i | cut -f1 -d""); file=$(wc -l $i | cut -f2 -d""); lines=$((lines + rowline)); echo"Lines["$lines"]" $file"has"$rowline"rows."; done && unset lines

产生这种输出:

1
2
3
4
5
6
7
8
9
10
11
Lines[75]  ./Db.h has 75rows.
Lines[143]  ./Db.cpp has 68rows.
Lines[170]  ./main.cpp has 27rows.
Lines[294]  ./Sqlite.cpp has 124rows.
Lines[349]  ./Sqlite.h has 55rows.
Lines[445]  ./Table.cpp has 96rows.
Lines[480]  ./DbError.cpp has 35rows.
Lines[521]  ./DbError.h has 41rows.
Lines[627]  ./QueryResult.cpp has 106rows.
Lines[717]  ./QueryResult.h has 90rows.
Lines[828]  ./Table.h has 111rows.

如果你想保持简单,去掉中间人,用所有文件名打电话给wc

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

或者用现代语法:

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

只要目录名或文件名中没有空格,就可以工作。只要你没有成千上万的文件(现代的shell支持非常长的命令行)。你的项目有74个文件,所以你有足够的空间增长。


1
2
$cd directory
$wc -l* | sort -nr

我的Windows系统上安装了"忙碌"框。这就是我所做的。

1
2
3
4
ECHO OFF
for /r %%G in (*.php) do (
busybox grep ."%%G" | busybox wc -l
)

我想检查多个文件类型,却懒得手工计算总数。所以我现在用这个一次就得到总数。

1
find . -name '*.js' -or -name '*.php' | xargs wc -l | grep 'total'  | awk '{ SUM += $1; print $1} END { print"Total text lines in PHP and JS",SUM }'

79351
15318
Total text lines in PHP and JS 94669

这允许您链接希望筛选的多个扩展类型。只需将它们添加到-name '*.js' -or -name '*.php'部分,并可能根据您的喜好修改otuput消息。


还有另一个获取所有文件总和的命令(当然是Linux)

1
find ./ -type f -exec wc -l {}  \; | cut -d' ' -f1 | paste -sd+ | bc

与其他答案的主要区别:

  • 使用find-exec,
  • 使用浆糊(带切口)
  • 使用BC

  • 非常简单

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


    首先更改要知道行数的目录。例如,如果我想知道名为sample的目录的所有文件中的行数。给$cd sample。然后尝试命令$wc -l *,这将返回每个文件的行数,以及最后整个目录中的行总数。


    我是这样做的:

    下面是linecount.c文件实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    int getLinesFromFile(const char*);

    int main(int argc, char* argv[]) {
       int total_lines = 0;
       for(int i = 1; i < argc; ++i) {
           total_lines += getLinesFromFile(argv[i]); // *argv is a char*        
       }    

       printf("You have a total of %d lines in all your file(s)
    "
    ,    total_lines);
       return 0;
    }


    int getLinesFromFile(const char* file_name) {
        int lines = 0;
        FILE* file;
        file = fopen(file_name,"r");
        char c = ' ';
        while((c=getc(file)) != EOF) if(c == '
    '
    ) ++lines;
        fclose(file);  
        return lines;
    }

    现在打开命令行:

    和类型gcc lineCount.c,然后类型./a.out *.txt。这将显示目录中以.txt结尾的文件的总行数。


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

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

    我还可以添加另一个OS X条目,这个条目使用普通的带exec的old find(我更喜欢使用xargs,因为我以前看到过非常大的find结果集与xargs的奇数结果)。因为这是针对OS X的,所以我还添加了对.h或.m文件的筛选-请确保一直复制到最后!

    1
    find ./ -type f -name"*.[mh]" -exec wc -l {}  \; | sed -e 's/[ ]*//g' | cut -d"." -f1 | paste -sd+ - | bc

    1
    cat \`find . -name"*.php"\` | wc -l