Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm puzzled by what actually defines an arg in xargs.
The man page seems to suggest that args are delimited by blanks (I assume that means whitespace). However the following script doesn't behave as I would expect. Here is an excerpt from man's DESCRIPTION section:

xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or new‐lines, and executes the command ...

It seems that perhaps xargs works in blocks of what the man-page calls items. Does this mean a null-delimited item, or a newline delimited item?

Basically, I don't understand why, in the following script, xargs treats the input as a single arg, even though the spaces (in stdin) are not protected. I expected xargs to treat stdin as 3 args, or at least reduce multiple spaces to a single space, but it does neither of these...

#!/bin/bash
if [[ $1 == "." ]] ;then  # act on a recursive call to self
    shift                 # scrap the 'recursive' arg
    printf '|%s|\n' "$@"  # print all 'xargs' args
    printf '|%s|\n' "$1"  # print only the first 'xargs' arg
    exit
fi
printf 'a    b    c\n' |xargs -I {} "$0" "." {}   

Here is the output; showing only a single arg was passed to the script.

|a    b    c|
|a    b    c|

But I would have expected 3 seperate args, like this:

|a|
|b|
|c|
share|improve this question

3 Answers 3

up vote 4 down vote accepted

Read what the manual page says about option -I, which you are using:

-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.

share|improve this answer
    
OMG! That was easy! I was looking at the wrong things... thanks ;) ... –  Peter.O Jan 19 '12 at 0:11

No, this isn't about “blocks” vs “items”, that's just shifting terminology. xargs takes input quoted with ' or " and delimited by blanks, except when certain options are passed.

Some options change to line-by-line processing with no quoting: -I, -L, -i (GNU), -l (GNU). The option -0 (where available) changes to null-delimited input with no quoting. The option -d (GNU) changes to a custom delimiter with no quoting.

share|improve this answer
    
Thanks... It is all in the man pages (somewhere :) –  Peter.O Jan 19 '12 at 0:15

One of the reasons for making GNU Parallel was to make it more predictable than xargs. https://www.gnu.org/software/parallel/history.html

If you get hit by the way xargs interprets arguments, consider using GNU Parallel instead.

You can install GNU Parallel simply by:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Watch the intro videos for GNU Parallel to learn more: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

share|improve this answer
    
Please only mention Parallel when you have a useful example, otherwise it seems like spam. You have copy-pasted this into several answers today. –  Mikel May 10 '12 at 3:31

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.