使用足够新的 Awk 和 GNU find 你可以做到
awk 'FNR==2 { if ($0 ~ /^#/) printf "%s\0", FILENAME; nextfile }' [0-9][0-9]/[0-9]/*.ini |
xargs -r0 echo rm
nextfile statement 是一个 POSIX 扩展,但可能不会出现在非常旧的 Awk 实现中。如果您的文件很小,也许只需取出 nextfile 并忍受我们通读每个文件末尾的轻微低效率,即使我们真的只需要检查第二行。
xargs 的 -0 选项是 GNU 扩展。如果你的文件名保证不包含换行符,你可能会逃脱
awk 'FNR==2 { if ($0 ~ /^#/) print FILENAME; nextfile }' [0-9][0-9]/[0-9]/*.ini |
xargs -r echo rm
最后,删除echo 以实际删除它打印的文件。
更详细地说,Awk 一次处理每个输入文件一行,并分别评估每个输入文件的脚本。内置变量FNR 设置为文件中的当前行号,FILENAME 是当前文件的名称。变量$0 包含整行,我们检查它是否匹配正则表达式^#(行首,紧跟文字# 字符);如果是这样,我们打印FILENAME(否则,此文件没有输出)。 nextfile 命令关闭当前文件并直接跳到参数列表中下一个文件的第一输入行(如果没有文件名需要处理,则停止处理)。
如果你有很多匹配的文件,你不能使用这样的通配符(你会得到“参数列表太长”);如果是这样,也许只是简单地恢复到你的循环。
您尝试的直接错误是您需要在# 周围加上引号(否则,它将将该行的其余部分标记为注释);但是当然,您的 grep 在文件中的任何位置查找该字符,并且您没有指定要检查的文件的路径。修复了即时错误,那将是
# Don't use, still broken
for i in stuff; do
for b in more stuff; do
grep -LZ '#' "$i/$b"/*.ini
done
done |
# or simply grep -LZ '#' [0-9][0-9]/[0-9]/*.ini
xargs -r0 echo rm
但同样,您不能轻易地解决这个问题,只查看每个文件的第二行。 (还要注意我如何在决赛 done 之外运行决赛 xargs。)