3

I often use grep twice with find in order to search for two patterns in a file as follows:

find . -name \*.xml | xargs grep -l "<beans" | xargs grep singleton

Then I ran into files with spaces which of course broke the above command. I modified it as follows to deal with the spaces:

find . -name \*.xml -print0 | xargs -0 grep -l "<beans" | xargs grep singleton

The option -print0 tells find to use print null as a separator instead of space and -0 tells xargs to expect a null. This works as long as none of the files I am looking for have spaces in their paths, but it breaks if they do.

So what I need is a flag to tell grep to print null as a speartor instead of newline.

Any ideas?

Kramer
  • 927
  • 2
  • 13
  • 30

4 Answers4

4

Good question. You can make grep -l use nulls as a delimiter with the Z option:

find . -name \*.xml -print0 | xargs -0 grep -lZ "<beans" | xargs grep singleton

You can also make xargs us the newline character as a delimiter. That should work for too:

find . -name \*.xml -print0 | xargs -0 grep -l "<beans" | xargs "--delimiter=\n" grep singleton

The first solution is better though.

Dan Bliss
  • 1,694
  • 13
  • 10
1
find . -name "*.xml"  -exec grep -q "<beans" {} \; -exec grep -q "singleton" {} \; -print

If you plan on using these file names in a later pipe sequence like you've done above change -print to -print0

Derek Schrock
  • 346
  • 1
  • 7
1

If you use GNU Parallel instead of xargs then you can avoid dealing with this, as GNU Parallel by default splits on newlines instead of white space.

find . -name \*.xml | parallel grep -l "<beans" | parallel grep singleton

Watch the intro videos to learn more: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Ole Tange
  • 31,768
  • 5
  • 86
  • 104
0

To avoid the space problem I'd use new line character as separator for xargs with the -d option:

xargs -d '\n' ...

For the two separate pattern search I'd use egrep:

egrep '(pattern one|pattern two)' ...

So my full solution would be:

find . -name \*.xml | xargs -d '\n' egrep '(pattern one|pattern two)'
Ray
  • 5,269
  • 1
  • 21
  • 12