我的文件夹树如下:
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
但是没有用。我不知道要使用sed
和awk
来做到这一点,但我不知道怎么做。
答案 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
。)