Reputation: 1058
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?
Upvotes: 3
Views: 3131
Reputation: 5659
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)'
Upvotes: 0
Reputation: 33685
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
Upvotes: 1
Reputation: 346
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
Upvotes: 1
Reputation: 1744
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.
Upvotes: 4