如何计算包含子目录的代码行

假设我想计算一个项目中的代码行数。 如果所有的文件都在同一个目录下,我可以执行:

cat * | wc -l 

但是,如果有子目录,这是行不通的。 为了这个工作猫将不得不有一个recursion模式。 我怀疑这可能是xargs的工作,但我想知道是否有一个更优雅的解决scheme?

首先,你不需要使用cat来计数线。 这是一个称为无用的猫 (UUoC)的反模式 。 要计算当前目录中文件的行数,请使用wc

 wc -l * 

然后find命令recursion子目录:

 find . -name "*.c" -exec wc -l {} \; 
  • . 是开始search的顶级目录的名称

  • -name "*.c"是你感兴趣的文件的模式

  • -exec给出要执行的命令

  • {}是find命令传递给命令的结果(这里是wc-l

  • \; 表示命令结束

这个命令产生一个列表,find所有文件的行数,如果你想要findfind的所有文件的总和,你可以使用find来列出文件(使用-print选项),而不是使用xargs来传递这个列表作为wc-l的参数。

 find . -name "*.c" -print | xargs wc -l 

编辑来解决Robert Gamble的评论(谢谢):如果在文件名中有空格或换行符(!),则必须使用-print0选项而不是-printxargs -null以便文件名列表以空终止的string。

 find . -name "*.c" -print0 | xargs -0 wc -l 

Unix的哲学是拥有只做一件事的工具,并且做得很好。

如果你想要一个代码高尔夫球的答案:

 grep '' -R . | wc -l 

单独使用wc -l的问题是它不能很好地下降,而且使用的是最后一个

 find . -exec wc -l {} \; 

不会给你一个总的行数,因为它为每个文件(LOL!)运行wc一次

 find . -exec wc -l {} + 

只要发现命中〜200k 1,2 字符的参数限制参数,而不是调用wc多次,每次只给你一个部分总结会感到困惑。

此外,上面的grep技巧在遇到二进制文件时不会在输出中添加多于一行的内容,这可能是非常有益的。

对于1个额外命令字符的代价,您可以完全忽略二进制文件:

  grep '' -IR . | wc -l 

如果你想在二进制文件上运行行数

  grep '' -aR . | wc -l 

限制脚注:

这个文档对于string大小限制还是一些令牌限制是有点模糊的。

 cd /usr/include; find -type f -exec perl -e 'printf qq[%s => %s\n], scalar @ARGV, length join q[ ], @ARGV' {} + # 4066 => 130974 # 3399 => 130955 # 3155 => 130978 # 2762 => 130991 # 3923 => 130959 # 3642 => 130989 # 4145 => 130993 # 4382 => 130989 # 4406 => 130973 # 4190 => 131000 # 4603 => 130988 # 3060 => 95435 

这意味着它非常容易。

我想你可能会卡在xargs

 find -name '*php' | xargs cat | wc -l 

chromakode的方法给出了相同的结果,但速度要慢得多。 如果你使用xargs,那么当你findfind时,就可以立即开始。

在Linux上的好解释:xargs vs. exec {}

尝试使用find命令,默认recursion目录:

find . -type f -execdir cat {} \; | wc -l

正确的方法是:

 find . -name "*.c" -print0 | xargs -0 cat | wc -l 

您必须使用-print0,因为Unix文件名中只有两个无效字符:空字节和“/”(斜杠)。 所以例如“xxx \ npasswd”是一个有效的名字。 实际上,你很可能会遇到名字中有空格的情况。 上面的命令会将每个单词记为单独的文件。

您可能还想使用“-type f”而不是-name来将search范围限制为文件。

在上面的解决scheme中使用cat或grep是浪费的,如果你可以使用相对较新的GNU工具,包括Bash:

 wc -l --files0-from = <(find。-name \ *。c -print0)

这可以处理空格,任意recursion和任意数量的匹配文件的文件名,即使它们超出命令行长度限制。

我喜欢在项目目录中的所有文件上使用findhead来“recursion地”,例如:

 find . -name "*rb" -print0 | xargs -0 head -10000 

好处是,头将添加您的文件名和path:

 ==> ./recipes/default.rb <== DOWNLOAD_DIR = '/tmp/downloads' MYSQL_DOWNLOAD_URL = 'http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.10-debian6.0-x86_64.deb' MYSQL_DOWNLOAD_FILE = "#{DOWNLOAD_DIR}/mysql-5.6.10-debian6.0-x86_64.deb" package "mysql-server-5.5" ... ==> ./templates/default/my.cnf.erb <== # # The MySQL database server configuration file. # ... ==> ./templates/default/mysql56.sh.erb <== PATH=/opt/mysql/server-5.6/bin:$PATH 

有关完整示例,请参阅我的博客文章:

http://haildata.net/2013/04/using-cat-recursively-with-nicely-formatted-output-including-headers/

注意我使用了“head -10000”,很明显,如果我的文件超过10,000行,这将会截断输出…但是我可以使用head 100000,但是对于“非正式项目/目录浏览”,这种方法对我来说效果很好。

如果您只想生成每行文件的总行数而不是行数,如下所示:

 find . -type f -exec wc -l {} \; | awk '{total += $1} END{print total}' 

效果很好。 这可以节省您在脚本中进一步进行文本过滤的需求。

 wc -cl `find . -name "*.php" -type f` 

这是一个Bash脚本,用于统计项目中的代码行。 它recursion地遍历一个源代码树,它排除了使用“//”的空行和单行注释。

 # $excluded is a regex for paths to exclude from line counting excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png" countLines(){ # $total is the total lines of code counted total=0 # -mindepth exclues the current directory (".") for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do # First sed: only count lines of code that are not commented with // # Second sed: don't count blank lines # $numLines is the lines of code numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l` total=$(($total + $numLines)) echo " " $numLines $file done echo " " $total in total } echo Source code files: countLines echo Unit tests: cd spec countLines 

以下是我的项目的输出结果:

 Source code files: 2 ./buildDocs.sh 24 ./countLines.sh 15 ./css/dashboard.css 53 ./data/un_population/provenance/preprocess.js 19 ./index.html 5 ./server/server.js 2 ./server/startServer.sh 24 ./SpecRunner.html 34 ./src/computeLayout.js 60 ./src/configDiff.js 18 ./src/dashboardMirror.js 37 ./src/dashboardScaffold.js 14 ./src/data.js 68 ./src/dummyVis.js 27 ./src/layout.js 28 ./src/links.js 5 ./src/main.js 52 ./src/processActions.js 86 ./src/timeline.js 73 ./src/udc.js 18 ./src/wire.js 664 in total Unit tests: 230 ./ComputeLayoutSpec.js 134 ./ConfigDiffSpec.js 134 ./ProcessActionsSpec.js 84 ./UDCSpec.js 149 ./WireSpec.js 731 in total 

请享用! – Curran

 find . -name "*.h" -print | xargs wc -l