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

时间:2010-03-23 15:53:27

标签: shell cygwin

我在从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,以及总行数if          指定了多个FILE。

它没有提及任何关于多个总行(中间总计数或其他)的内容,那么谁应该责备在这里?

4 个答案:

答案 0 :(得分:5)

正在发生的事情是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组合的输出,跳过“总计”行和总和总计自己。

答案 1 :(得分:3)

你多次调用wc - 对于xargs提供的每个“批量”输入参数一次。你每批获得一个。

另一种方法是使用临时文件和--files0-from的{​​{1}}选项:

wc

答案 2 :(得分:2)

命令行长度在cygwin下比在标准linux盒子上更受限制,而xargs必须将输入拆分为尊重这些限制。您可以使用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的答案,您不需要创建其他文件,您可以通过将-作为参数传递给--files0-from来将搜索结果直接传递给wc:

find . -name '*.vb' -print0 | wc -l --files0-from=-

答案 3 :(得分:0)

为了避免在使用大量文件路径作为命令行参数提供wc实用程序时生成具有“总计数”的多行,您可以使用中间xargs到{{1} }文件的内容到cat的标准输入(参见piping output of find to xargs wc gives unreasonable totals)。

如果你的wc命令没有Xavier提到的wc,这是一种解决方法。

--files0-from