views:

135

answers:

2

I'm trying to escape characters within backticks in my bash command, mainly to handle spaces in filenames which cause my command to fail.

The command I have so far is:

grep -Li badword `grep -lr goodword *`

This command should result in a list of files that do not contain the word "badword" but do contain "goodword".

+1  A: 

How about rewrite it to:

grep -lr goodword * | grep -Li badword
William
Your suggestion will output the files where the file contains `goodword` and the file _name_ does not contain `badword`
jk
That's true; it needs an xargs... Thanks for pointing this out :)
William
+3  A: 

Your approach, even if you get the escaping right, will run into problems when the number of files output by the goodword grep reaches the limits on command-line length. It is better to pipe the output of the first grep onto a second grep, like this

grep -lr -- goodword * | xargs grep -Li -- badword

This will correctly handle files with spaces in them, but it will fail if a file name has a newline in it. At least GNU grep and xargs support separating the file names with NUL bytes, like this

grep -lrZ -- goodword * | xargs -0 grep -Li -- badword

EDIT: Added double dashes -- to grep invocations to avoid the case when some file names start with - and would be interpreted by grep as additional options.

jk
Thanks for the tip! I'm still getting some weird behavior. When I try to run this command, I get the following output: root@domain [/path]# grep -lrZ goodword * | xargs -0 grep -Li badword grep: invalid option -- k Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. (standard input)
Ian Silber
@Ian: Do you have a file whose name starts with a `-` in the directory? In that case, remember to also add `--` before the actual arguments to `grep`. I've modified the answer accordingly.
jk
Awesome - that totally worked. Thanks a bunch.
Ian Silber