Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
3  
"if -I option is not specified, it is default to -I{}" -- this is incorrect, at least with GNU xargs. –  jjlin Oct 7 '13 at 1:18
    
I understand my mistake. I should specify either xargs file or xargs -I{} file {}. Shouldn't be xargs file {}. I guess when explicitly specifying -I{}, the bash will treat it as file "Hello World". Without -I{}, it is treated as file Hello World. –  foresightyj Oct 7 '13 at 4:01
1  
(1) This discussion has little to do with the shell (bash). (2) It’s good that you know the -1 option to ls, but it’s on by default when the output of ls is a file or a pipe, so you don’t need it here. (3) You’re confusing -I with the deprecated -i (lower case I) option. -ifoo is equivalent to -Ifoo, but plain -i is equivalent to -I{}. But use -I{}. (4) If you really want to do what you say you want to do, why not just say file *? –  Scott Oct 8 '13 at 0:36
    
@Scott My original intent was to write ` find . -name "*.mov" | xargs -I{} file {}` to find all mov files recursively and run file on them. But I came up with a simpler example using ls. You are right. For that, file * is the best. –  foresightyj Oct 8 '13 at 2:23
1  
find has -exec. –  Cristian Ciupitu Oct 22 '13 at 11:03

1 Answer 1

up vote 0 down vote accepted

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 mistakeny uses {}:

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

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

If you want to explicly 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/.
share|improve this answer
    
That is very clear. Even though your answer is a bit late, but reading it really reinforces my understanding. –  foresightyj Nov 10 '13 at 5:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.