如何删除所有不包含指定文本的文件。
我了解删除具有指定文本的文件的解决方案,但我需要删除不包含指定模式的文件。
以下命令创建不包含“成功运行”的文件列表:
grep -c "successful run" *.out | grep -v ":1" > err.txt
我希望直接删除这些文件。
答案1
您最初的识别适当文件的方法是
grep -c "successful run" *.out | grep -v ":1"
存在缺陷。主要问题:
- 如果一个文件中有两行或更多匹配的行怎么办?
grep ":0"
似乎更符合问题标题中的条件(“不包含模式的文件”)。 - 如果文件名中有
:1
(或) 会怎么样?这样看起来就更好了。:0
grep ':0$'
- 如果从第一个传递的任何文件名中都有换行符怎么办
grep
?
我说不要依赖grep -c
;依赖退出状态,也grep
就是1
如果没有选择任何行。
for f in *.out; do
[ -f "$f" ] && {
grep -q -- "successful run" "$f"
[ "$?" -eq 1 ] && rm -i -- "$f"
}
done
笔记:
[ -f "$f" ] && …
将不会让其grep
与匹配的目录、fifo 等一起工作*.out
;只能与常规文件一起工作。--
解释的含义和意义这里。万一有文件名以 开头-
,它可能会误认为是选项。处理此问题的另一种方法是for f in ./*.out; do …
。这样,每个扩展名都$f
以 开头,./
因此它不能以 开头-
。- 我
rm -i
以防万一使用了。测试解决方案后,您可能想要省略-i
。 grep … || rm …
更糟糕。当发生真正的错误(例如权限被拒绝)时,退出状态grep
大于1
;那时您可能不想删除该文件。我的解决方案测试退出状态是否正好是1
。- 您的原始代码不会下降到子目录中,我的也不会。如果您想要递归,那么支持它的 shell(例如带有
shopt -s globstar
和 的Bash**
)或基于 的解决方案find
将很有用。
答案2
考虑到您的文件只有一次“成功运行”或没有,那么:
要找到匹配的文件,您可以执行以下操作:
grep -l "successful run" *.out > err.txt
找到并删除它们:
grep -l "successful run" *.out | xargs rm
要查找不匹配的文件,请执行以下操作:
grep -vl "successful run" *.out > ok.txt
找到并删除它们:
grep -vl "successful run" *.out | xargs rm
这些标志的含义是:
-l lists the files with matches
-v/--invert-match inverts the matching logic