6

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 {}

2 Answers 2

15

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" {} \; | ...
3
  • depending on what your "further processing" is, the multiple-xargs version may be more (or less) preferable than the "sh -c" version. Dec 7, 2009 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, 2009 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). Dec 8, 2009 at 2:56
3

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

5
  • 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, 2009 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, 2009 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, 2009 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, 2009 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, 2009 at 2:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .