在Linux上,如何找到所有包含字符串的文件并将其删除?


17

我想删除所有包含string的文件foo。如何在Linux中使用bash做到这一点?


该字符串是其文件名吗?
rɑːdʒɑ

3
请说明:您要删除名称包含foo(例如myfoo.jpg)的文件还是包含字节序列的foo文件(其中可能包含二进制文件,而恰好恰好包含该字节序列)?
hammar

Answers:


33

这是一种安全的方法:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l 打印与搜索模式匹配的文件的文件名。
  • -rfoo对给定目录中的模式执行递归搜索.。如果这不起作用,请尝试-R
  • -I(大写i)会导致二进制文件(如PDF)被跳过。
  • -Z 确保文件名以零(即nul)结尾,以便包含空格的名称不会被错误地解释(即,多个名称而不是一个)。
  • xargs -0将文件名从grep传送到rm -f,以零(nul)个字节分隔单词(请记住-Z来自的选项grep)。
  • --通常会被忘记,但是标记选项的结束并允许删除名称开头的文件非常重要-

如果您想查看要删除的文件,只需删除该| xargs -0 rm -f --部分,然后将Z选项保留为grep

另一个用户建议类似以下内容,由于它不安全,因此不应运行

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

如果我有ImportantStuff不想删除和obsolete ImportantStuff包含的文件foo,则在运行此命令时会丢失ImportantStuff(而不是 obsolete ImportantStuff!),因为$files在解释该命令时,它们在空格处会分开。以这种方式将文件名列表放入标量shell变量中是危险的。


17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

这将以递归方式搜索包含的文件foo-exec仅当第一个exec成功退出(即grep匹配)时,才运行第二个。echo如果输出看起来正确,请进行Dryrun并删除。

或者

$ find -type f -exec grep -q "foo" {} \; -print

$ find -type f -exec grep -q "foo" {} \; -delete

如Lekensteyn所建议。


4
...可以缩写为:(find -type f -exec grep -q 'foo' {} \; -delete引号{}是多余的,find也可以删除文件。)。请注意,它grep接受正则表达式。如果要搜索foo.bar,请对此进行转义或传递-F选项以将模式视为文字。
Lekensteyn

-exec echo rm "{}" \;没有使用的理由-delete吗?
vartec

1
@vartec不,我用-delete。使用第二个-exec和适当的echo 演示起来更容易。
AdrianFrühwirth'13

1
键入-print(或-ls更详细)比容易-exec echo rm "{}" \'。无需外部实用程序。
Lekensteyn

1
如果使用rm {},请使用rm-{},这样就不会插入文件名本身中的任何特殊字符。例如,在您具有写入权限的任何目录中触摸“ -rf /” ...
atk 2013年

1

我会按照阿德里安所说的做,

但是我会在foo之前添加单词边界,以免意外删除包含“食物”的文件(除非它要删除包含食物的所有内容)。

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

因此,我在删除之前重定向了输出,因此可以在删除之前进行检查:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete

一旦能够发表评论,就应该将类似的内容作为评论发表。
FSMaxB

是的,我首先尝试了但后来意识到我还不允许发表评论。
Petter H
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.