使用find命令查找行数

使用find命令查找行数

考虑位于以下​​位置的 R 源代码存储库:https://cloud.r-project.org/src/base/R-3/R-3.4.4.tar.gz。我将存储库解压缩到一个文件夹中。现在,我想知道目录中有多少行。所以,我尝试了以下命令:

find . -type f -exec wc -l {} \+

产生 394968 但如果我尝试以下命令:

find . -type f -exec cat {} \+ | wc -l

它产生 1848857!

为什么这两个看似相似的命令操作会find产生如此截然不同的结果?并且,查找行数的正确方法是什么,最好使用命令行实用程序而不是编写小工具脚本?

答案1

您提到的第一个命令find . -type f -exec wc -l {} +实际上是说“运行wc -l尽可能多的文件,直到所有文件都被处理”。这可以运行wc多次!

另一方面,find . -type f -exec cat {} + | wc -l可以运行 cat多次,但只会运行wc一次。 (更详细地说,这是因为在这种情况下cat被调用find,它可以并且确实决定运行它,无论它想要多少次,而管道字符之后的部分,wc -l超出了 的范围find,因此由您运行外壳,只需一次。)

你说第一个命令“产生 394968”,但事实并非如此;在我的系统上,其输出以以下内容结尾:

(Many more lines elided...)
     23 ./po/Makefile.win
     64 ./po/README
      1 ./VERSION-NICK
     97 ./README
 258450 total

然而,通过添加grep total,我们可以看到它wc实际上运行了两次:

$ find . -type f -exec wc -l {} + | grep total
 1590407 total
 258450 total

事实上,1590407 加 258450 就是 1848857,这与第二条命令一致。


模糊地暗示了为什么在该命令的版本wc中运行多次的解释find -exec wc +查找手册页:

-exec command {} +

    -exec操作的变体对选定的文件运行指定的命令,但命令行是通过在末尾附加每个选定的文件名来构建的;该命令的调用总数将远小于匹配的文件数。命令行的构建方式与xargs构建其命令行的方式大致相同。

请注意这表示“远少于……”而不是“仅一次”。这 xargs 的文档提示--max-chars如果用户未设置其选项,则会自动设置:

--max-chars=max-chars
-s max-chars

    最多使用max-chars每个命令行的字符数,包括命令和初始参数以及参数字符串末尾的终止空值。最大允许值取决于系统,计算方式为 exec 的参数长度限制减去环境大小,减去 2048 字节的余量。如果该值大于128KiB,则使用128Kib作为默认值;否则,默认值为最大值。

这限制了一次调用可以传递的文件名数量wc,这解释了为什么对于大量文件,wc会发生多次调用,每个调用都在输入的一个分区上进行操作。

相关内容