如何计算目录中每个文件的行数,然后创建 n 行文件数的摘要

如何计算目录中每个文件的行数,然后创建 n 行文件数的摘要

我正在尝试创建一个目录中有多少个文件有 n 行的摘要。我用来wc -l * | sort打印每个文件名的行数。我想要实现的是目录的摘要,该目录将产生:

56 5
60 6
3  7

等等,其中第一列代表文件数,第二列代表行数。

我查看了一个 awk 命令awk 'END{print NR}' directory/*,它返回整个目录中的行数。我考虑过printf格式化wc -l输出的解决方案。任何帮助将不胜感激!谢谢

答案1

使用 GNU awk,你可以这样做:

find . -type f -print0 | gawk '
  BEGIN {
    RS = "\0"
    while ((getline < "-") > 0) ARGV[ARGC++] = $0
    if (ARGC == 1) exit
    RS = "\n"
  }
  ENDFILE {count[FNR]++}
  END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in count) print count[i], i
  }'

find -print0我们通过从的输出中读取以 NUL 分隔的文件来设置要在 BEGIN 语句中处理的文件列表。

或者与以下相同perl(注意空文件将被忽略):

find . -type f -print0 | perl -0 -ne '
  BEGIN{@ARGV = <STDIN>; $/ = "\n"}
  if (eof) {$count{$.}++; close ARGV}
  END {print "$count{$_} $_\n" for sort {$a <=> $b} keys %count}'

请注意,它们计算行数(无论是否分隔),同时wc -l计算换行符的数量。例如,对于使用printf foo > filewhere创建的文件wc -l会报告 0 但perl/ gawk1,这会有所不同。

使用wcPOSIXly,你可以这样做:

find .//. -type f -exec wc -l {} + | LC_ALL=C awk '
  /\/\// {count[$1]++}
  END {for (i in count) print count[i], i}' | sort -k2n

通过使用.//.,我们可以知道文件路径在输出中从哪一行开始wc(因为//不能出现在其他地方),并且行计数将是该行的第一个字段,因此我们可以可靠地处理包含换行符的文件路径。这还跳过了传递多个参数的调用在末尾打印的total行,因为它不包含.wc//

使用 GNUgrep或兼容版本,您还可以执行以下操作:

LC_ALL=C grep -rch '^' . | sort -n | uniq -c

我们正在c计算匹配的行数^,即有一个开头,因此所有文件中的所有行都r在 中递归.-h以跳过打印文件名。LC_ALL=C不必费心将内容解码为文本(grep鉴于该正则表达式,GNU 至少可能会优化该解码)。

请注意,所有这些也计入隐藏文件。

要跳过它们,您可以将命令更改find为:

LC_ALL=C find . -name '.?*' -prune -o -type f -print0

grep -r尽管您可以删除-r并将find文件列表传递给 ,但GNU 没有等效项grep

LC_ALL=C find . -name '.?*' -prune -o -type f -exec grep -ch {} +

答案2

假设您的“wc -l *”按照您需要的方式计算行数,例如没有有趣的文件名,那么您可以使用 uniq -c 为您进行计数。 head -n -1 是去掉末尾的“total”行:

wc -l *|head -n -1|sort|awk '{print $1}'|uniq -c

相关内容