用特定行删除mutliple目录中的文件

时间:2018-12-18 09:25:12

标签: linux command-line text-processing

我的文件夹树如下:

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

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

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

我尝试使用:

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

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

1 个答案:

答案 0 :(得分:1)

有了最新的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并忍受我们在每个文件末尾所读取的效率低下的问题。

-0的{​​{1}}选项是GNU扩展。如果保证您的文件名不包含换行符,则可能可以摆脱

xargs

最后,删除awk 'FNR==2 { if ($0 ~ /^#/) print FILENAME; nextfile }' [0-9][0-9]/[0-9]/*.ini | xargs -r echo rm 以实际删除其打印的文件。

更详细地讲,Awk一次处理每个输入文件一行,并分别评估每个输入文件上的脚本。内置变量echo设置为文件中的当前行号,而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 之外运行最终xargs。)