Contents

计算目录中的所有代码行数

1. 概述

在本文中,我们将了解如何计算一个目录以及多个目录和子目录中包含的文件的行数。此外,我们将讨论多种类型文件的情况,并了解如何计算数百万行代码。

作为说明,我们使用wget、WordPress、HAproxy 和 Linux Kernel 等项目来演示不同的用例。另外,我们将看一下*wc *、find/xargs 命令。我们还将特别关注如何将它们结合起来处理复杂的文件组织。

此外,我们将了解如何以正确的方式使用这些工具来获得准确的结果。

2. 计算文件中的行数

首先,请注意,在不提供任何参数的情况下,wc命令会计算并打印作为参数传递的每个给定文件的行数、字数和字节数:

$ wc /usr/include/stdio.h
870  4202 29660 /usr/include/stdio.h

其次,要计算并仅显示行数,我们使用*-l选项或更长的-lines*选项:

$ wc -l /usr/include/stdio.h
870 /usr/include/stdio.h

3. 计算目录中文件的行数

为了说明如何计算一个目录中包含的多个文件的行数,我们将获取 wget 工具的源代码。它是大多数 GNU/Linux 发行版下可用的网络下载实用程序。所有的源代码文件都在src目录下,包括头文件。

首先,让我们从只计算 C 语言文件*.c开始:

$ wc -l wget-1.21.1/src/*.c 
   101 src/build_info.c
   1084 src/connect.c
   1230 src/convert.c
   ...
   95 src/xattr.c
  54300 total

其次,我们可以使用tail -1命令选择wc输出的最后一行。因为正如我们所见,wc命令会打印每个*.c*文件的行数:

$ wc -l wget-1.21.1/src/*.c | tail -1
54300 total

除了 C 语言文件,我们还要计算头文件 ( *.h ) 的行数。要计算这两种类型的文件,我们这样做:

$ wc -l wget-1.21.1/src/*.[ch] | tail -1
57241 total

4. 计算多个目录中的文件行数

为了了解如何计算包含在不同目录中的多个文件中的行数,我们选择了 HAproxy 项目。同样,它的代码、C 语言文件*.c可以在src目录中找到。头文件*.h分为两个子目录,include/importinclude/haproxy目录。

所以要统计HAproxy源代码的行数,我们可以这样做:

$ cd haproxy
$ find src/ include/ -name '*.[ch]' | xargs wc -l | tail -1
256475 total

首先,find命令分别获取srcinclude目录中的所有 C 语言文件和头文件。

其次,所有文件都通过xargs一个一个地传递给wc命令。因此wc命令将计算每个文件的行数。

最后,我们通过tail命令选择输出的最后一行。正如我们所看到的,它表示所有文件的总行数。

一个常见的错误是在没有xargs命令的情况下将wcfind一起使用。实际上,这将计算完全错误的文件数:

$ find src/ include/ -name '*.[ch]' | wc -l |tail -1
403

这里 403 是找到的文件数,而不是这些文件中的行数。

4.1. 计算多个目录中多语言文件的行数

除了计算多目录中文件的行数之外,我们通常还需要处理多语言的情况。为了证明这一点,我们可以使用包含 PHP、JavaScript 和 CSS 文件的 WordPress 项目。

以类似的方式,我们可以将  -o选项添加到find命令(o表示逻辑或),因为我们有多种类型的文件。

让我们数一下 PHP、JavaScript 和 CSS 文件的行数:

$ find  WordPress-5.7.2/ -type f -name '*.php' -o -name '*.js' -o -name '*.css' | xargs wc -l | tail -1
1248529 total

另一种执行此操作的方法是使用命令替换运算符。Bash 通过在子 shell 中执行find命令并将命令替换替换为find的输出来执行扩展:

$ wc -l $(find . -type f -name '*.php' -o -name '*.js' -o -name '*.css') | tail -1
1248529 total

5. 数百万行文件

到目前为止,我们使用的方法对于中小型项目非常有用,但是如果我们将它们用于大型项目,它们不能给我们正确的答案。

例如,Linux 内核有许多目录、子目录和数千个文件。在这种情况下,find命令将文件列表拆分为多个片段,并使wc命令打印每个子列表的总数,而不是整个列表的总数。

此外,如果我们尝试将find命令的输出作为参数传递给wc命令,文件名列表将太长。因此,我们将超过wc命令的行长限制,它会给我们一个错误:

$ wc -l $(find linux/ -type f -name '*.[ch]')
bash: /usr/bin/wc: Argument list too long

在这种情况下,执行此操作的正确方法是使用find命令的*-exec选项。因此,它将为每个文件独立运行wc*命令。由于它不会计算出所有文件行的总数,因此我们使用awk 命令来计算所有列的数量。

$ find linux/ -type f -name '*.[ch]' -exec wc -l {} \; | awk '{ total += $1 } END {print total}'
28085235

如我们所见,Linux Kernel 有超过 2800 万行代码!