使用特定行删除多个目录中的文件

Removing file in mutliple directory with specific line

我有这样的文件夹树:

00 -- 0
   -- 1
   ...
   -- 9
 ...
99 -- 0 
   -- 1
   ...
   -- 9

在每个文件夹中,我都有带有某种奇怪文本的 .ini 文件。

如何删除第二行开头为 # 的文件?

我尝试使用:

for i in {00..99}; do for b in {0..9}; do grep -LZ -- # *.ini | xargs
-r0 rm; done; done

但是没有用。我想知道如何使用 sedawk 来做到这一点,但我不知道怎么做。

使用足够新的 Awk 和 GNU find 你可以做到

awk 'FNR==2 { if ([=10=] ~ /^#/) printf "%s[=10=]", 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 ([=11=] ~ /^#/) print FILENAME; nextfile }' [0-9][0-9]/[0-9]/*.ini |
xargs -r echo rm

最后,删除 echo 以实际删除它打印的文件。

更详细地说,Awk 一次一行地处理每个输入文件,并分别评估每个文件的脚本。内置变量 FNR 设置为文件中的当前行号,FILENAME 是当前文件的名称。变量 [=21=] 包含整行,我们检查它是否匹配正则表达式 ^# (行的开头,紧跟文字 # 字符);如果是这样,我们打印 FILENAME(否则,该文件没有输出)。 nextfile 命令关闭当前文件并直接跳到参数列表中下一个文件的第一输入行(或者如果没有文件名需要处理则停止处理)。

如果你有很多匹配的文件,你不能像那样使用通配符(你会得到 "argument list too long");如果是这样,也许可以简单地恢复到原来的循环。

您尝试的直接错误是您需要在 # 周围加上引号(否则,它会将该行的其余部分标记为注释);但当然,您的 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

但同样,您无法轻松解决此问题,只查看每个文件的第二行。 (另请注意我如何 运行 最后 xargs 在最后 done 之外。)