Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am using find and getting a list of files I want to grep through. How do I pipe that list to grep?

share|improve this question

2 Answers 2

up vote 28 down vote accepted

Well, the generic case that works with any command that writes to stdout is to use xargs, which will let you attach any number of command-line arguments to the end of a command:

$ find … | xargs grep 'search'

Or to embed the command in your grep line with backticks or $(), which will run the command and substitute its output:

$ grep 'search' $(find …)

Note that these commands don't work if the file names contain whitespace, or certain other “weird characters” (\'" for xargs, \[*? for $(find …)).


However, in the specific case of find the ability to execute a program on the given arguments is built-in:

$ find … -exec grep 'search' {} \;

Everything between -exec and ; is the command to execute; {} is replaced with the filename found by find. That will execute a separate grep for each file; since grep can take many filenames and search them all, you can change the ; to + to tell find to pass all the matching filenames to grep at once:

$ find … -exec grep 'search' {} \+
share|improve this answer
    
Should be noted that first two forms do not works with filenames containing spaces. –  enzotib Sep 7 '11 at 19:09
    
I prefer find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED. While -exec + is very efficient, it does not exist on all version of find. –  Arcege Sep 7 '11 at 19:11
    
Sadly I can not check you correct 3 times. –  James Andino Sep 7 '11 at 19:43
1  
I suggest using the -exec, rather than than the xargs. If you use the -exec in find, it will create only one shell to grep for the content. If you use the xargs, it will create two shells: one for the find and the other for the xargs. –  user14470 Jan 18 '12 at 18:32

Some versions of grep (e.g. on non-embedded Linux or BSD or Mac OS X) have a -r option to make a recursive search. On OpenBSD, use -R (and there's no --exclude as in the example below). This covers simple combinations of find with grep.

If your implementation doesn't have the -R flag, or if you want fancier file matching criteria, you can use the -exec primary of find to make it execute grep. A few older find implementations don't support -exec+; on these systems, use a ; instead of the + (this will call grep once per file, so it'll be slower, but otherwise the result will be the same). Note the /dev/null trick to cause grep to show the file name even if it happens to be called on a single file (GNU grep and FreeBSD/NetBSD/OSX grep have a -H option to achieve the same effect).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
share|improve this answer
    
GNU grep has -H option to always print filename. –  enzotib Sep 8 '11 at 12:11

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.