Xargs -I replace-str option difference

bashxargs

From my understanding, the following should mean exactly the same:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

if -I option is not specified, it is default to -I{}.

I want to list all files in the current directory and run file command on each of them. Some have spaces in their names. However, I noticed the difference. See below:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

With -I{} explicitly specified, blanks in file names are treated as expected.

Best Answer

The -I requires a defined placeholder. The -i option will assume {} is the placeholder. This was where I found any assumption of {} in man xargs at least on Cygwin and CentOS.

xargs called without either option does not need the placeholder and it just appends the STDIN to the end of the arguments.

Just add echo to your examples to see what xargs is doing:

$ ls -1
Hello World/

Your example mistakenly uses {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

so the file cmd sees args of {} Hello World and errors.

If you want to explicitly use {} in your xargs call:

$ ls -1 | xargs -I{} echo file {}
file Hello World/

Or with No placeholder:

$ ls -1 | xargs echo file
file Hello World/

xargs as called above does not need the {}. It appends the STDIN to the end of the command without a placeholder. The use of {} usually means you want the STDIN somewhere in the middle of the cmd to execute, as in:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
Related Question