http://unix.stackexchange.com/questions/20262/how-do-i-pass-a-list-of-files-to-grep
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' {} \+
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 offind
withgrep
.If your implementation doesn't have the
-R
flag, or if you want fancier file matching criteria, you can use the-exec
primary offind
to make it executegrep
. A few olderfind
implementations don't support-exec
…+
; on these systems, use a;
instead of the+
(this will callgrep
once per file, so it'll be slower, but otherwise the result will be the same). Note the/dev/null
trick to causegrep
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).