Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I need a way to run grep on a list of files which may contain spaces in the file name. On a list of files with no spaces, it's pretty straight forward and easy. Also, I know how to deal with spaces in the file names for find and xargs. I'm just looking for a way to use grep with the -print0 command.

I'm looking for text inside the file, not in the filename...

This lists all files:

find * -print 0 | xargs -0 -i{} echo {}

but say I have to do a grep (or some other command) inbetween.

This lists files which contain "howdy doody" inside the file:

find * | xargs grep -l "howdy doody" | xargs -i{} echo {}

This doesn't work, grep doesn't know how to recognize null terminated lines. Did I miss something in grep's man page?

find * -print0 | xargs grep -l "howdy doody" | xargs -0 -i{} echo {}
share|improve this question

2 Answers 2

up vote 8 down vote accepted

Are you looking for "howdy doody" in the filename, or within the file?

# find files with "howdy doody" in the filename
find * -name "*howdy doody*" -print0 | xargs -0 ...

xargs is what you need to use to split the null-terminated output from find -print0. In your example, the echo is extraneous; don't bother with it.

# find files containing "howdy doody"
find * -print0 | xargs -0 grep -l "howdy doody"

# find files containing "howdy doody" and do further processing

# multiple xargs version
find * -print0 | xargs -0 grep -l "howdy doody" | xargs -i{} do-something "{}"

# "sh -c" version
find * -print0 | xargs -0 -i{} sh -c 'grep -l "howdy doody" "{}" && do-something "{}"'

# notes: 
#   "sh -c" allows us to run a complex command with a single xargs
#   "{}" handles spaces-in-filename
#   handles any &&, ||, | command linking

You can also run your command directly from the find with -exec. The difference is that find -exec runs the command once per file found; xargs adds filenames to the end of the command (up to system limit), so it runs the command fewer times. You can simulate this with xargs -n1 to force xargs to only run one command per input.

# grep once per file
find * -exec grep -l "howdy doody" {} \; | ...
share|improve this answer
    
depending on what your "further processing" is, the multiple-xargs version may be more (or less) preferable than the "sh -c" version. –  quack quixote Dec 7 '09 at 21:37
    
the echo in my example is just to debug/clarify the question. I like this approach, tho yet somewhat verbose. Thanks –  Roy Rico Dec 8 '09 at 2:48
    
gotcha. i thought maybe it was a placeholder for additional commands (useful when you're trying to figure out syntax for something). –  quack quixote Dec 8 '09 at 2:56

You can do it all in one command, using the -exec argument to find:

find . -name "*howdy doody*" -exec echo I found file {} hooray \;

The escaped semicolon at the end of the command to execute is required by find.

Or, if you're looking in the contents of files:

grep -R "howdy doody" *

This will show all text matches, add -l to the grep to just get a list of files

share|improve this answer
    
I'm trying to find :howdy doody" inside the file, not in the name. but it's good to know that the -exec option uses {} for the var, i didn't know that. –  Roy Rico Dec 8 '09 at 2:42
    
Oh ok, your example commands show using grep to find "howdy doody" in the file names. See my second example. The other guy's answers should work too, but simpler commands are easier to remember, and should in theory be quicker if it's just a single command instead of multiple. –  davr Dec 8 '09 at 2:47
    
yea, sorry that's an error on my part, i forgot the extra xargs in the command. I updated my question to reflect that. sorry! –  Roy Rico Dec 8 '09 at 2:50
    
I don't like grep -R option as it doesn't have enough pipes in it. I like my unix commands how i like my head shops, with a lot of pipes in 'em! haha seriously tho, thanks, i learned something else –  Roy Rico Dec 8 '09 at 2:56
    
Also, keeping davr as answered because it works generically with other commands, not just grep. You're answer is better (shorter) for this specific example tho. –  Roy Rico Dec 8 '09 at 2:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.