假设我有一个名为“/home/ben/files”的目录,其中包含 100 个随机命名的文本文件。在 100 个文本文件中,有些文本文件中只包含“删除”一词。
例如file1.txt、file2.txt、file3.txt、file4.txt、file5.txt.....等
应该如何删除包含该模式的此类文件?
假设我有一个名为“/home/ben/files”的目录,其中包含 100 个随机命名的文本文件。在 100 个文本文件中,有些文本文件中只包含“删除”一词。
例如file1.txt、file2.txt、file3.txt、file4.txt、file5.txt.....等
应该如何删除包含该模式的此类文件?
至少使用 GNU grep,您可以尝试:
警告:这将通过 ; 的子文件夹递归
/home/ben/files
。如果您不希望这样,则需要采取更多预防措施。(感谢 cas 在评论中建议使用空分隔符。)
使用 GNU
find
:首先进行一些设置,创建一个目录,在其中创建 100 个空文件,并将“DELETEME”附加到其中一些文件:
接下来,列出包含 DELETEME 的文件:
这将打印所有
grep -q DELETEME
返回 true 的文件。请注意,使用\;
结束-exec
here(而不是+
)很重要,因为每个文件都需要单独测试(否则退出代码grep -q
将针对当前正在运行的整批文件)。find
的谓词默认情况下是与在一起的,因此粗略的英文翻译是“grep AND delete any files where the previous-exec
return true”。这将适用于包含任何有效字符的文件名,包括 shell 元字符、换行符和其他空格。
最后,要删除匹配项,请使用
-delete
代替-print
:如果您使用的
find
是没有的版本,则-delete
可以-exec
再次使用:我们可以在这里使用
+
第二个-exec
,因为文件名不需要单独删除,批量删除它们会更好更快。当然,您可以使用任何 find 的其他谓词 - 例如
-maxdepth 1
防止递归。顺便说一句,如果您想删除仅包含“DELETEME”而没有其他内容的文件,您需要更像这样:
首先确保我们至少有一个这样的文件。
打印包含 DELETME 以及其他任何内容的文件列表:
在这种情况下,我们使用 regexp
^DELETEME$
而不是 justDELETEME
- 这是因为我们只想匹配包含 DELETEME 的行,而该行上没有任何其他内容。如果您想在一行中允许可选的前导和/或尾随空格,请使用^[[:space:]]*DELETEME[[:space:]]*$
然后我们将其与另一个
-exec grep
匹配包含除^DELETEME$
.我们现在可以继续列出包含 DELETEME 的文件,除了那些包含其他内容的文件,使用
!
(boolean NOT) 来否定第二个-exec
:请注意,
./files/001
此列表中缺少文件,这正是我们想要的。还要注意
!
紧接在第二个-exec
谓词之前。这很重要,也很容易错过,所以我明确指出。在此示例中,第一个
-exec grep
获取包含 的文件列表^DELETEME$
,然后它与包含除 ^DELETEME$ 以外的任何文件的文件进行 NOT AND 运算。-print
可以替换为或-delete
实际-exec rm {} +
删除文件。PS:对于比这更复杂的事情,我倾向于编写一个 perl 脚本,可能使用File::Find模块。
有些东西用过程语言风格编写比使用非常长的命令行(谓词链与布尔运算符绑定在一起)要容易得多
find
(很容易忘记逻辑链)。