-1

Having a thousand of data files (same extension) in a directory, how to delete those which contain a specific parameter statement?

For example, if I wented to delete all files containing the line

Key = 0

could I do something like

grep -i "Key = 0" * | rm *
Kusalananda
  • 333,661
  • 1
    You mean the file would contain the literal string Key = 0? – jesse_b Aug 11 '20 at 19:22
  • 4
    The output of grep would include the filename and the line containing the string so instead of passing it to rm, it would just run the rm command on * which is everything in the directory and it would delete the files and give an error for directories because the -r switch isn't used. Do you want to delete the files that have that string in their contents? If so, provide an example of what it might look like. Do you also want to delete files that have Key = 01 or MyKey = 05? – Nasir Riley Aug 11 '20 at 19:28

2 Answers2

1

You can use the following command in the shell. This should do the job if pattern to be searched is Key = 0

grep -lrIZ "Key = 0" . | xargs -0 rm -f --

Generic command:

grep -lrIZ "<Pattern to be searched in the file>" . | xargs -0 rm -f --
AdminBee
  • 22,803
Jaks
  • 41
1

The main issue with the pipeline using grep+rm is that rm does not read from its standard input stream, which means that it does not read anything from the grep command on the left-hand side of the pipe.

Instead, the rm * on the right-hand side of the pipe would ignore all input and execute rm on every visible filename in the current directory.

Ignoring the issue with rm not reading its standard input, your grep command has two main issues:

  1. It outputs matching lines with filenames. This would be of no use to rm as we need to know only the filenames of the files we want to delete.
  2. It matches Key = 0 as a substring, which means it also matches Crypto Key = 0x01 etc.

find . -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +

or, with GNU find (and some others),

find . -type f -exec grep -q -F -x 'Key = 0' {} \; -delete

Both of these would look for regular files in the current directory or below, and for each found file, it would execute grep -q -F -x 'Key = 0'. This grep command would return an exit status signalling whether there is a line in the file that is exactly Key = 0 (and nothing else).

The second find command will delete the file using its -delete predicate if such a line is found. The first find command would collect the pathnames of the files containing this line and then run rm -f on batches of these.

The flags used with grep are

  • -q, for quiet operation. The utility does not output matching lines but exits successfully after the first match or with a non-zero exit status if the file does not contain a match.
  • -F, for fixed string matching. We are matching with a string, not a regular expression.
  • -x, to find full-line matches only. This has the same effect as if using a regular expression anchored to both the start and end of the line.

I'm not using -i with grep here as that would also delete files containing lines like KEY = 0 and kEY = 0 etc., and you have said nothing about these case variations.

Would you want the find command to be restricted to a particular filename suffix, like .ext, then use -name '*.ext' in the find command before the execution of grep. For example:

find . -name '*.ext' -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +
Kusalananda
  • 333,661