为了列出正好有 n
行的文件,可以这样做
n=5
find . -name "*.txt" | xargs wc -l | awk -v n=${n} -F" " '{if ($1==n) {print $2} }'
但是这个解决方案非常慢,因为它首先计算每个文件的行数,然后只选择那些有 n
行的文件。计算行数并在到达 n+1
行时停止的进程会更有效率(尤其是在处理包含大量行的大文件时)。
如何有效地列出正好有 n
行的文件?
请注意,对于特殊情况,每行的大小完全相同,那么可能可以这样做
n=5
sizePerLine=500
find . -name '*.txt' -size $(( ${n} * ${sizePerLine} ))
最佳答案
我认为以下会更快:
find . -name "*.txt" -exec awk -v n="$n" 'FILENAME != prevfile {if(prevfnr==n) print prevfile} {prevfile = FILENAME; prevfnr = FNR; if(FNR>n) {nextfile;}} END{if (FNR==n) {print FILENAME} }' {} +
工作原理:
- 使用
-exec ... {} +
使用find
为每个文件执行命令,并让它在每次调用时传递许多参数 awk -v n="$n"
调用awk
并定义一个名为n
的awk
变量与 shell 变量n
相同的值
FILENAME != prevfile {if(prevfnr==n) print prevfile
检查当前文件是否与上一条记录相同,如果不相同,则查看前一个文件是否完全n
条记录,如果有则打印该文件的名称{prevfile = FILENAME; prevfnr = FNR; if(FNR>n) {nextfile;}}
用当前的FILENAME
更新prevfile
变量,用当前的prevfnr
变量更新当前FNR
。另外,如果我们当前的文件记录超过n
,则跳转到下一个文件,这里不做任何处理END{if (FNR==n) {print FILENAME}
最后看看最后一个文件是否也正好有n
条记录
有趣的是,我发现这实际上给出了与使用 wc -l
的版本不同的结果,尽管我认为这个可能更正确。对于我目录中最后一行不包含行结束字符的文件 wc -l
将报告行数,不计算最后一个“未终止”行,但这里的解决方案将计算它。
Arg,我没有意识到 nextfile
是 GNU 主义。如果我已经将自己限制在这一点上,我们可以使它更干净,因为
find . -name '*.txt' -exec awk -v n="$n" 'FNR > n {nextfile;} ENDFILE{if (FNR==n) {print FILENAME} }' {} +
在我看来,POSIX awk
没有很好的快捷方式来跳转到下一个文件,这是该解决方案提高效率所需的关键
关于bash - 如何有效地列出正好有 `n` 行的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39431845/