递归计算文件中的行数,按文件扩展名分组

fal*_*ets 5 bash pipe sed find awk

问题

我有一个充满文件的 git 存储库,其中大部分是文本。

我想知道有

  • n以以下结尾的文件中的代码行.py
  • m以以下结尾的文件中的代码行.md
  • o以以下结尾的文件中的代码行.yaml
  • p没有扩展名的文件中的代码行
  • ETC

笔记:

  • 我希望这是递归的,检查文件夹内部
  • 我想排除.git顶级文件夹中的目录
  • 我想忽略二进制文件是可能的(注意我有一些没有扩展名的文本文件,以及一些没有扩展名的二进制文件)
  • 我想不区分大小写。组.csv.CSV
  • 我想忽略空行(或仅空白行)
  • 如果有像myfile.yaml.j2我这样的文件,不在乎它是否被计入组.j2.yaml.j2.

fal*_*ets 8

尝试这个

find ./ -not -path "./.git/*" -type f -exec wc -l {} + |
    awk '{print tolower($0)}' |
    sed -e '$ d' | 
    sed -e "s#/.*/##g" |
    sed -e "s/\./ \./g" |
    awk '
        { if ( NF <= 2 ) { count["none"] += $1 } else { count[$NF] += $1 } }
        { next }
        END { for (group in count) printf("%d%s%s\n", count[group], OFS, group) }
    ' |
    sort -n
Run Code Online (Sandbox Code Playgroud)

细分:

  • find ./递归查找该目录下的对象
  • -not -path "./.git/*"排除.git
  • -type f文件而不是目录
  • -exec wc -l {} +对于每个文件,运行字数统计实用程序 ( wc)。这包括空行,因此不满足问题的所有要求。
  • awk '{print tolower($0)}'变为小写
  • sed -e '$ d'删除最后一行,这是所有文件的行总和
  • sed -e "s#/.*/##g"删除文件的路径,例如a/something.egg/blah应该算作无扩展名,而不是.egg/blah扩展名
  • sed -e "s/\./ \./g" search/replacewith.`,所以文件扩展名是它自己的单词
  • awk '{ if ( NF <= 2 ) { count["none"] += $1 } else { count[$NF] += $1 } } { next } END { for (group in count) printf("%d%s%s\n", count[group], OFS, group) }'这是一件大事。awk功能强大,但不是超级清晰
    • count是一本字典
    • if (NF <= 2)如果少于 3 个“单词”,即没有扩展名
    • count["none"] += $1增加字典中的一个元素,key是字符串文字none,通过添加该文件中的行数来增加它,这是第一个单词,即$1
    • count[$NF] += $1字典中增加一个元素,key是$NF该行的最后一个单词,它是扩展名,by$1是该行的第一个单词,它是这个文件的行数
    • { next }next对所有行重复,只执行一次后面的操作
    • for (group in count)for 循环,内联
    • printf(...)格式化输出字符串,如123 .abc(如果以 结尾的文件中有 123 行.abc
  • sort -n按升序对结果进行排序,-n意味着按数字而不是字符串排序