【问题标题】:How can I count all the lines of code in a directory recursively?如何递归计算目录中的所有代码行?
【发布时间】:2010-11-24 10:02:42
【问题描述】:

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

我们不需要忽略 cmets,因为我们只是想得到一个粗略的想法。

wc -l *.php 

该命令适用于给定目录,但它会忽略子目录。我在想下面的评论可能有用,但它返回 74,这绝对不是这种情况......

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

从目录中递归地输入所有文件的正确语法是什么?

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    试试:

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

    或(当文件名包含空格等特殊字符时)

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

    The SLOCCount tool 也可能有所帮助。

    它会给出准确的源代码行数 你指向的层次结构,以及一些额外的统计数据。

    排序后的输出:

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

    【讨论】:

    • cloc.sourceforge.net 可能值得作为 sloccount 的替代品(更多语言但更少信息)
    • 还包含文件:find . -name '*.php' -o -name '*.inc' | xargs wc -l
    • 当有很多文件时,这将打印多个数字(因为wc会运行多次。也不会处理许多特殊文件名。
    • @idober: find . -name "*.php" -not -path "./tests*" | xargs wc -l
    • 如果目录名中包含空格...上述命令失败!!
    【解决方案2】:

    对于另一个单行:

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

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

    【讨论】:

    • +1 同上...永远搜索...所有其他“查找”命令只返回了实际文件的数量......这里的 -print0 内容为我提供了实际的行数! !!谢谢!
    • 我找到的最佳解决方案。我参数化了路径和文件类型,并将此代码添加到我路径上的脚本中。我打算经常使用它。
    • @TorbenGundtofte-Bruun - 参见man find .. print0 和 xargs -0 让您可以对名称中包含空格或其他奇怪字符的文件进行操作
    • @TorbenGundtofte-Bruun - 另外,xargs 中的 -0 对应于 print0,它是一种处理空格的编码/解码。
    • 如果您需要多个名称过滤器,我发现(至少使用 MSYSGit 版本的 find),您需要额外的括号:( find . \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 cat ) | wc -l
    【解决方案3】:

    您可以使用专门为此目的而构建的cloc 实用程序。它报告每种语言的行数,以及其中有多少是 cmets 等。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
    -------------------------------------------------------------------------------
    

    【讨论】:

    • 这是一个可爱的工具,运行良好并且在最后提供有用的统计数据。喜欢它。
    • 请注意,您可以使用 cygwin(或其他类似的端口/环境)在 Windows 上运行 Unix 命令。对我来说,拥有这种非常有用的访问权限是必要的。 unix 命令行很神奇。我特别喜欢 perl 和正则表达式。
    • CLOC 和 SLOCCount 在 2015 年中期的 macbook 上运行良好。请注意,对于 127k Java Android 项目,它们的数字很接近,但并不完全相同。另请注意,iOS 等价物有 2 倍的 LoC;因此,SLOCCount 中的“成本”指标可能会关闭(或者 iOS 开发人员的收入可能是 Android 开发人员的 2 倍。:-)
    • 您是否考虑编辑此问题的开头以明确 cloc 是跨平台的,因为它只是一个 Perl 脚本?
    • 完美,当然在 Windows bash 中也能正常工作。
    【解决方案4】:

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

    wc -l **/*.php
    

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

    shopt -s globstar
    

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

    【讨论】:

    • 为简单起见,我赞成这一点,但我只想指出,它似乎不会递归搜索目录,它只检查当前目录的子目录。这是在 SL6.3 上。
    • 这取决于你的 shell 和你设置的选项。 Bash 需要 globstar to be set 才能工作。
    • @PeterSenna,使用当前的 3.9.8 内核存档,命令 wc -l **/*.[ch] 总共找到 15195373 行。不确定您是否认为这是“非常低的价值”。同样,您需要确保在 Bash 中启用了globstar。您可以通过shopt globstar 查询。要显式启用它,请执行shopt -s globstar
    • @MichaelWild 这是一个很好的解决方案,但是如果你有大量的.php 文件,它仍然会溢出ARG_MAX,因为wc 不是内置的。
    • @AlbertSamuel 不,您需要比较两种方法生成的文件列表。正如@BroSlow 所提到的,我的方法存在不适用于大量文件的问题。如果find 生成的路径包含空格,则接受的答案将失败。这可以通过分别使用 print0--nullfindxargs 调用来解决。
    【解决方案5】:

    在类 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
    -------------------------------------------------------------------------------
    

    【讨论】:

    • @moose 在技术上 simtao 专门提到它是为 Windows 用户提供的解决方案,根本没有提到 linux 或 unix。
    • @moose Table 被编辑到他的答案中比我的答案晚得多,现在两者看起来确实相似。
    • 我喜欢。 cloc真的很整洁。但是这个名字是什么意思?
    • 它现在也在 Windows 上!假设你有 chocolatey: choco install cloc
    • @ManoelVilela 计算代码行数
    【解决方案6】:

    您没有指定有多少文件或所需的输出是什么。

    这可能是您正在寻找的:

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

    【讨论】:

    • 这将起作用,只要文件不多:如果文件很多,结果会得到几行(xargs 会将文件列表拆分为几个子列表)
    • 啊,是的。这就是为什么我说他没有具体说明有多少文件。我的版本更容易记住,但如果你有多个文件,Shin 的版本会更好。我正在投票。
    • 我需要调整它以用于单引号过于严格的函数: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 的 slocount,但它不知道 *.js,@ 987654325@.
    【解决方案7】:

    另一种变化:)

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

    这将给出总和,而不是逐个文件。

    find 之后添加. 以使其工作。

    【讨论】:

    • 两个答案总和。
    • 至少在 cygwin 中,我有更好的结果:$ find -name \*\.php -print0 | xargs -0 cat | wc -l
    • 在达尔文上,这只是一个总数:find . -name '*.php' | xargs cat | wc -l ... 而这给出了一个文件一个文件和一个总数:find . -name '*.php' | xargs wc -l
    【解决方案8】:

    使用find-execawk。我们开始:

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

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

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

    【讨论】:

    • 从功能上讲,这工作得很好,但是在大型列表(linux 源代码)上它真的很慢,因为它为每个文件启动一个 wc 进程,而不是为所有文件启动一个 wc 进程。我使用此方法将其计时为 31 秒,而使用 find . -name '*.c' -print0 |xargs -0 wc -l 则为 1.5 秒。也就是说,这种更快的方法(至少在 OS X 上)最终会打印“总计”多次,因此需要进行一些额外的过滤才能获得正确的总计(我在答案中发布了详细信息)。
    • 这有利于处理无限数量的文件。干得好!
    • 这是处理大量 GB 和文件时更好的解决方案。在 cat 的形式上执行 wc 很慢,因为系统首先必须处理所有 GB 才能开始计算行数(使用 200GB 的 jsons、12k 文件进行测试)。先做wc 然后计算结果要快得多
    • @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
    【解决方案9】:

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

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

    【讨论】:

    • 这和你想的不太一样。找 。 -name '.[am]' 与 find 相同。 -name '.[a|m]' both 将查找所有以 .m 或 .a 结尾的文件
    • 但第二个也会找到以 .| 结尾的文件,如果有的话。所以 [h|c|cpp|php|cc] 最终与 [hcp|] 相同。
    • 不推荐使用反引号,更喜欢$()
    • 这在 Cygwin 下工作。当然,“C:\”驱动器必须遵循 cygwin 约定,例如: wc $(find /cygdrive/c//SomeWindowsFolderj/ -type f | egrep "\.(h|c|cpp|php| cc)")
    【解决方案10】:

    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
    

    【讨论】:

      【解决方案11】:

      有一个叫做sloccount 的小工具可以计算目录中的代码行数。

      应该注意,它做的比你想要的更多,因为它忽略空行/cmets,按编程语言对结果进行分组并计算一些统计数据。

      【讨论】:

      • 对于 Windows,LocMetrics 完成这项工作
      • 重复接受的答案(尽管同时发布)。
      【解决方案12】:

      工具Tokei 显示有关目录中代码的统计信息。 Tokei 将显示文件数、这些文件中的总行数以及按语言分组的代码、cmets 和空白。 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
      -------------------------------------------------------------------------------
      

      关注the instructions on the README file in the repository即可安装Tokei。

      【讨论】:

        【解决方案13】:

        你想要一个简单的for 循环:

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

        【讨论】:

        • 与建议 xargs 的答案相比,这不是矫枉过正吗?
        • 不,内森。 xargs 答案不一定会将计数打印为单个数字。它可能只打印一堆小计。
        • 如果文件名包含空格,这个程序会做什么?换行符呢? ;-)
        • 如果你的文件名包含新行,我会说你有更大的问题。
        • @ennukiller 这个问题的数量,首先它会在带有空格的文件上中断。在循环之前设置IFS=$'\n' 至少可以为除名称中带有换行符的文件之外的所有文件修复它。其次,你没有引用'*.php',所以它会被shell扩展而不是find,并且ergo实际上不会在子目录中找到任何php文件。 -print 也是多余的,因为它隐含在没有其他操作的情况下。
        【解决方案14】:

        仅适用于来源:

        wc `find`
        

        要过滤,只需使用grep:

        wc `find | grep .php$`
        

        【讨论】:

          【解决方案15】:

          一个简单的快速的,将使用find 的所有搜索/过滤功能,当文件太多时不会失败(数字参数溢出),可以很好地处理名称中带有有趣符号的文件,没有使用xargs,并且不会启动大量无用的外部命令(感谢+ for find's -exec)。给你:

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

          【讨论】:

          • 我正要自己发布一个变体(使用\; 而不是+,因为我不知道),这个答案应该是正确的答案。
          • 我做了( find . -type f -exec cat {} \; |wc -l )然后我看到了这个。只是想知道这个解决方案中的“--”和“+”是什么意思,以及与我的版本在外部命令数量方面的区别。
          • @grenix:您的版本将为找到的每个文件生成一个新的cat,而\+ 版本将在一次调用中将找到的所有文件提供给cat-- 是标记选项的结束(这里有点不必要)。
          • 我不明白这是如何避免参数数量溢出的。如果我确实'找到 . -type f -exec cat -- {} + |more' 和 ' ps aux|grep "cat "' 在另一个终端我得到类似 '... 66128 0.0 0.0 7940 2020 pts/10 S+ 13:45 0:00猫 -- ./file1 ./file2 ...'
          【解决方案16】:

          我知道该问题被标记为,但您尝试解决的问题似乎也与 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
          

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

          【讨论】:

            【解决方案17】:

            到目前为止,没有一个答案涉及文件名带有空格的问题。

            此外,如果树中路径的总长度超过 shell 环境大小限制(在 Linux 中默认为几兆字节),则所有使用 xargs 的对象都会失败。

            这是一个以非常直接的方式解决这些问题的方法。子shell 负责处理带有空格的文件。 awk 总计单个文件 wc 输出的流,因此它永远不会耗尽空间。它还将exec 限制为仅文件(跳过目录):

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

            【讨论】:

            • 你可以增强它以省略 cmets 吗?
            • 我不认为评论部分是为了来回居高临下。谢谢。
            • 真的,这是一个诚实的问题。能够在比让其他人在 SO 上为你做这件事所需的时间更短的时间内自己做这种事情绝对是一个渴望成为软件工程师的人应该具备的技能。我不是屈尊俯就。如果你自己弄清楚这一点,你就会领先。
            【解决方案18】:

            如果您想保持简单,请去掉中间人,只需使用所有文件名调用 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`
            • 很惊讶它不是最佳答案
            【解决方案19】:

            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 of '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 definition of a line。使用grep -c ^,您正在计算incomplete lines 的数量,这样不完整的行不能出现在text file 中。
            • 我知道。实际上,只有最后一行可能不完整,因为它没有 EOL。想法正在计算所有行,包括不完整的行。这是非常常见的错误,只计算完整的行。数完后,我们在想“为什么我错过了最后一行???”。这是答案为什么,以及如何正确地做到这一点。
            • 或者,如果你想要一个班轮:find -type f -name '*.php' -print0 | xargs -0 grep -ch ^ | paste -sd+ - | bc 请参阅此处了解bc 的替代品:stackoverflow.com/q/926069/2400328
            • 谁在乎最后一行?特别是考虑到文件中的所有 空行。反正都是近似
            【解决方案20】:

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

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

            【讨论】:

            • 在构建过程中生成的代码或文件被复制的项目中,排除目录很重要
            【解决方案21】:

            对于 Windows,一个简单快捷的工具是 LocMetrics

            【讨论】:

            • 如果他们使用 bash,OP 不太可能在 Windows 上。
            • @VanessaMcHale 问题标题和描述都没有明确要求仅适用于 unix 的解决方案。所以基于 Windows 的解决方案是可以接受的。当我在寻找类似的解决方案时,谷歌也将我指向了这个页面。
            • 这条评论帮助了我。我试过了,效果很好。
            【解决方案22】:

            您可以使用名为codel (link) 的实用程序。这是一个简单的 Python 模块,可以用彩色格式计算行数。

            安装

            pip install codel
            

            用法

            要计算 C++ 文件的行数(带有 .cpp.h 扩展名),请使用:

            codel count -e .cpp .h
            

            你也可以忽略一些 .gitignore 格式的文件/文件夹:

            codel count -e .py -i tests/**
            

            它将忽略tests/文件夹中的所有文件。

            输出如下:

            您还可以使用-s 标志缩短输出。它将隐藏每个文件的信息并仅显示有关每个扩展名的信息。示例如下:

            【讨论】:

            • 有没有办法对所有文本文件执行此操作,而不仅仅是特定的扩展名?
            • @AaronFranke 现在没有办法了。
            【解决方案23】:

            如果您希望您的结果按行数排序,您只需将| sort| sort -r-r 用于降序排列)添加到第一个答案,如下所示:

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

            【讨论】:

            • 由于xargs wc -l 的输出是数字,因此实际上需要使用sort -nsort -nr
            【解决方案24】:

            很简单:

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

            【讨论】:

            • 如果其中一个文件名中有空格或换行符,它将失败
            【解决方案25】:

            不同的东西:

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

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

            【讨论】:

            • 也可能溢出 ARG_MAX
            【解决方案26】:

            使用Z shell (zsh) glob 非常简单:

            wc -l ./**/*.php
            

            如果您使用的是 Bash,则只需升级即可。绝对没有理由使用 Bash。

            【讨论】:

              【解决方案27】:

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

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

              【讨论】:

              • 您可以使用grep total 而不是grep -v total - 它将对wc 给出的中间和求和。重新计算中间和没有意义,因为wc 已经这样做了。
              【解决方案28】:

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

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

              【讨论】:

                【解决方案29】:

                如果你只需要总行数,比方说,你的 PHP 文件,如果你安装了 GnuWin32,即使在 Windows 下你也可以使用非常简单的一行命令。像这样:

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

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

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

                【讨论】:

                • 在上面的示例中,我使用的是 Windows 的 bash 而不是 cmd.exe,这就是为什么有正斜杠“/”而不是反斜杠“\”的原因。
                【解决方案30】:

                虽然我喜欢这些脚本,但我更喜欢这个脚本,因为它还显示每个文件的摘要,只要总数:

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

                【讨论】:

                • “……只要一共……”:你不是说”……还有一共…… "?
                猜你喜欢
                • 2020-06-08
                • 2016-11-20
                • 2016-06-04
                • 2019-11-10
                • 2010-12-31
                • 1970-01-01
                • 2012-02-27
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多