On Linux, how can I find all files that contain a string and delete them?
Solution 1:
Here is a safe way:
grep -lrIZ foo . | xargs -0 rm -f --
-
-l
prints file names of files matching the search pattern. -
-r
performs a recursive search for the patternfoo
in the given directory.
. If this doesn't work, try-R
. -
-I
(capitali
) causes binary files like PDFs to be skipped. -
-Z
ensures that file names are zero- (i.e., nul-)terminated so that a name containing white space does not get interpreted in the wrong way (i.e., as multiple names instead of one). -
xargs -0
feeds the file names fromgrep
torm -f
, separating words by zero (nul) bytes (remember the-Z
option fromgrep
). -
--
is often forgotten but it is very important to mark the end of options and allow for removal of files whose names begin with-
.
If you would like to see which files are about to be deleted, simply remove the | xargs -0 rm -f --
part, and leave off the Z
option to grep
.
Another user suggested something like the following, which you should not run because it is unsafe:
files=`grep foo * | cut -d: -f1`
rm -f $files # unsafe, do not run it!
If I have files ImportantStuff
that I do not want to delete and obsolete ImportantStuff
containing foo
, then I lose ImportantStuff
(and not obsolete ImportantStuff
!) when I run this command, because $files
gets broken apart at spaces when it is interpreted. It is dangerous to put a list of filenames into a scalar shell variable in this way.
Solution 2:
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;
This recursively searches for files containing foo
. The second -exec
is only run if the first exec
exits successfully, i.e. if grep
matches. Dryrun and remove the echo
if the output seems correct.
Or alternatively
$ find -type f -exec grep -q "foo" {} \; -print
and
$ find -type f -exec grep -q "foo" {} \; -delete
as suggested by Lekensteyn.
Solution 3:
I'd do what Adrian says,
But I'd add word boundries arond the foo so as to not accidentaly delete files containing "food" (unless it is deleting everything containing food is what you want.)
$ find -type f -exec grep -q "\<foo\>" {} \; -delete
acutally, I'd redirect the output before deleteing so I could review before deleting:
$ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete