Why does find . -name "*.xml" | xargs grep FOO
returns matchs with filenames, while find . -name "*.xml" | xargs -i -sh -c "grep FOO {}"
doesn't?
3 Answers
Unless it's a typo in posting your question there shouldn't be a hyphen before sh
:
The reason you don't get filenames in the output is that grep
is being run with a single file as an argument. To force filename output use -H
.
find . -name "*.xml" | xargs -I {} sh -c "grep -H FOO {}"
Also, -i
for xargs
was deprecated around version 4.2.9. You should use -I {}
.

- 1,431
- 17
- 27

- 346,391
- 90
- 374
- 439
As a previous answer said, the difference is that grep is being invoked for each file and grep doesn't report the filename if only one file is specified on the command line unless the -H (--with-filename) flag is given.
Why is grep being invoked for each file? That is because (like it or not) the use of the -I (or -i) flag to xargs forces the command to be run once for each argument, like using flag "-L 1" to xargs.
From the manual page:
-I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.

- 81
- 1
- 2
you can just use
find . -name "*.xml" | xargs -I{} grep FOO {}
and you may use -H
or -n
in grep
command as you need.

- 97
- 1
- 3
-
1that does not provide the answer to the stated question. – andr Mar 14 '13 at 02:42