为什么wc实用程序会用“total”生成多行?

我在一个从Cygwin运行的shell脚本中使用了wc实用程序,并且我注意到其输出中有多行“total”。

以下函数用于计算我的源文件中的行数:

count_curdir_src() {
    find . '(' -name '*.vb' -o -name '*.cs' ')' 
        -a '!' -iname '*.Designer.*' -a '!' -iname '.svn' -print0 | 
    xargs -0 wc -l
}

但是它对于某个目录的输出如下所示:

$ find . '(' -name '*.vb' -o -name '*.cs' ')' -a '!' -iname '*.Designer.*' -a '!' -iname '.svn' -print0 | xargs -0 wc -l
     19 ./dirA/fileABC.cs
    640 ./dirA/subdir1/fileDEF.cs
    507 ./dirA/subdir1/fileGHI.cs
   2596 ./dirA/subdir1/fileJKL.cs
(...many others...)
     58 ./dirB/fileMNO.cs
     36 ./dirB/subdir1/filePQR.cs
 122200 total
  6022 ./dirB/subdir2/subsubdir/fileSTU.cs
    24 ./dirC/fileVWX.cs
(...)
    36 ./dirZ/Properties/AssemblyInfo.cs
    88 ./dirZ/fileYZ.cs
 25236 total

它看起来像wc重置过程中的某个地方。 它不能由文件名或目录名称中的空格字符引起,因为我使用-print0选项。 它只发生在我最大的源代码树上时。

那么,这是wc中还是Cygwin中的错误? 或者是其他东西? wc手册页说:

为每个FILE打印换行符,字和字节计数,如果指定了多个FILE,则打印总行。

它没有提到任何关于多条总线(中间总数或某物)的事情,那么谁来责怪呢?


你多次调用wc - 对xargs提供的每个“批处理”输入参数一次。 你每批得到一个总数。

一种替代方法是使用临时文件和wc--files0-from选项:

$ find . '(' -name '*.vb' -o -name '*.cs' ')' -a '!' -iname '*.Designer.*' -a 
    '!' -iname   '.svn' -print0 > files

$ wc --files0-from files

发生什么事是xargs多次运行wc 。 默认情况下, xargs批量尽可能多的参数,因为它认为它可以应用到它应该运行的命令的每个调用中,但是如果文件太多,它会在文件的子集上多次运行该命令。

有几种方法可以解决这个问题。 第一个,如果你有太多文件会中断,就是跳过xargs并使用shell。 这在Cygwin上可能无法正常工作,但看起来像这样:

wc -l $(find . '(' -name '*.vb' -o -name '*.cs' ')' 
    -a '!' -iname '*.Designer.*' -a '!' -iname '.svn' )

而且你也失去了print0的能力。

另一种方法是使用awk (或perl )脚本处理find / xargs组合的输出,跳过“总计”行,并自己总结总计。


命令行长度在cygwin下比在标准的linux下更受限制,并且xargs必须将输入分割以遵守这些限制。 您可以使用xargs --show-limits来检查xargs --show-limits

在cygwin上:

$ xargs --show-limits < /dev/null
Your environment variables take up 4913 bytes
POSIX upper limit on argument length (this system): 25039
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 20126
Size of command buffer we are actually using: 25039

在centos上:

$ xargs --show-limits < /dev/null
Your environment variables take up 1816 bytes
POSIX upper limit on argument length (this system): 2617576
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2615760
Size of command buffer we are actually using: 131072

并且建立在@ JonSkeet的答案上,你不需要创建一个额外的文件,你可以直接将查找结果通过-作为参数传递给wc,作为--files0-from参数:

find . -name '*.vb' -print0 | wc -l --files0-from=-
链接地址: http://www.djcxy.com/p/57163.html

上一篇: Why does the wc utility generate multiple lines with "total"?

下一篇: Prevent wget from recursing into excluded directories