On Linux, how can I find all files that contain a string and delete them?

44,677

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 pattern foo in the given directory ..  If this doesn't work, try -R.
  • -I (capital i) 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 from grep to rm -f, separating words by zero (nul) bytes (remember the -Z option from grep).
  • -- 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
Share:
44,677

Related videos on Youtube

Kitsos
Author by

Kitsos

Updated on September 18, 2022

Comments

  • Kitsos
    Kitsos over 1 year

    I want to delete all files that contain the string foo. How can I do this using bash in Linux?

    • rɑːdʒɑ
      rɑːdʒɑ about 11 years
      that string is its file name ?
    • hammar
      hammar about 11 years
      Please clarify: do you want to delete files whose name contains foo (e.g. myfoo.jpg), or files that contain the byte sequence foo (which may include binary files which just so happen to contain that sequence of bytes)?
  • Lekensteyn
    Lekensteyn about 11 years
    ... which can be shortened to: find -type f -exec grep -q 'foo' {} \; -delete (the quotes around {} are redundant, find is also able to delete files.). Note that grep accepts a regular expression. If you want to search for foo.bar, either escape this or pass the -F option to treat the pattern as literal.
  • vartec
    vartec about 11 years
    any reason to use -exec echo rm "{}" \; and not -delete?
  • Adrian Frühwirth
    Adrian Frühwirth about 11 years
    @vartec No, I'd use -delete. It's just easier to demonstrate with the second -exec and echo in place.
  • Lekensteyn
    Lekensteyn about 11 years
    It is easier to type -print (or -ls for more verbosity) than -exec echo rm "{}" \'. No need for external utilities.
  • atk
    atk about 11 years
    if you use rm {}, use rm -- {}, so that any special characters in the file name itself don't get interpolated. For example, touch '-rf /' in any directory where you have write permissions...
  • FSMaxB
    FSMaxB about 11 years
    As soon as you are able to post comments, you should post things like that as comments.
  • Petter H
    Petter H about 11 years
    yes I tried first but then realised that I'm not allowed to post comments yet .
  • mpelzsherman
    mpelzsherman over 3 years
    I tried this but got "File name too long".