我在从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。
它没有提及任何关于多个总行(中间总计数或其他)的内容,那么谁应该责备在这里?
答案 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