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

- 93,103
- 40
- 240
- 233

- 5,016
4 Answers
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' {} \+

- 93,103
- 40
- 240
- 233
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' .

- 829,060
find ... | while read line; do grep <regex> "$line"; done

- 283
-
Although your approach is quite straightforward, please find the time to add a minimum of explanation. Also, please note that this shares the same problem that most of the other answers have in that it relies on parsing the output of
find
which should be avoided due to possible problems with special characters in filenames (although that may be repairable depending on the shell used). – AdminBee Sep 18 '20 at 13:13
example :
search for a file which have "Delay" in its name and which have "Create" somewhere inside the found file
find . | grep Delay | xargs grep 'Create'
it should then, if it finds something, display each line where the word 'Create' is written.

- 201
- 3
- 6
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 07 '11 at 19:11-exec
, rather than than thexargs
. If you use the-exec
infind
, it will create only one shell to grep for the content. If you use thexargs
, it will create two shells: one for thefind
and the other for thexargs
. – Jan 18 '12 at 18:32$ find … -exec grep 'search' {} \+
form is much the fastest. – gogoud Nov 14 '16 at 10:32