Kramer
Kramer

Reputation: 1058

find with spaces in filename

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

Answers (4)

Ray
Ray

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

Ole Tange
Ole Tange

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

Derek Schrock
Derek Schrock

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

Dan Bliss
Dan Bliss

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

Related Questions