Subtle difference in using xargs and xargs -i

Why find . -name "*.xml" | xargs grep FOO find . -name "*.xml" | xargs grep FOO find . -name "*.xml" | xargs grep FOO returns matches with file names, and find . -name "*.xml" | xargs -i -sh -c "grep FOO {}" find . -name "*.xml" | xargs -i -sh -c "grep FOO {}" find . -name "*.xml" | xargs -i -sh -c "grep FOO {}" - no?

+4
source share
3 answers

If this is not a typo when posting your question, there should not be a hyphen before sh :

The reason you don't get the file names in the output is because grep runs with one file as an argument. To force the output of the file name, use -H .

 find . -name "*.xml" | xargs -I {} sh -c "grep -H FOO {}" 

Also, -i for xargs deprecated around version 4.2.9. You must use -I {} .

+7
source

As mentioned in the previous answer, the difference is that grep is called for each file, and grep does not report the file name if only one file is specified on the command line, if the -H flag (--with-filename).

Why is grep called for every file? This is because (for example, whether it is or not) using the -I (or -i) flag for xargs causes the command to run once for each argument, for example, use the "-L 1" flag for xargs.

On 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. 
+4
source

you can just use

 find . -name "*.xml" | xargs -I{} grep FOO {} 

and you can use -H or -n in the grep as you need.

0
source

Source: https://habr.com/ru/post/1342275/


All Articles