here is my problem in short
$ echo 'for i in $@; do echo arg: $i; done; echo DONE' > /tmp/test.sh $ echo "ac\nbc\ncc\n" | xargs bash /tmp/test.sh arg: ac arg: bc arg: cc DONE
Which is what i expect, but
$ echo "ac s\nbc s\ncc s\n" | xargs -d \n bash /tmp/test.sh arg: ac arg: s arg: bc arg: s arg: cc arg: s DONE
Shouldn't the output be?
arg: ac s arg: bc s arg: cc s DONE
How do I get the 2nd output with xargs?
xargs will run the first two commands in parallel, and then whenever one of them terminates, it will start another one, until the entire job is done. The same idea can be generalized to as many processors as you have handy. It also generalizes to other resources besides processors.
Overview. xargs (short for “eXtended ARGuments”) is a command on Unix and most Unix-like operating systems. It converts input from standard input (STDIN) into arguments to a command.
The xargs utility allows you to build and execute commands from standard input. It is usually used in combination with other commands through piping. With xargs , you can provide standard input as argument to command-line utilities like mkdir and rm .
The -c flag to sh only accepts one argument while xargs is splitting the arguments on whitespace - that's why the double quoting works (one level to make it a single word for the shell, one for xargs).
Try:
printf %b 'ac s\nbc s\ncc s\n' | xargs -d '\n' bash /tmp/test.sh
You neglected to quote the \n
passed to -d
, which means that just n
rather than \n
was passed to xargs
as the delimiter - the shell "ate" the \
(when the shell parses an unquoted string, \
functions as an escape character; if an ordinary character follows the \
- n
in this case - only that ordinary character is used).
Also heed @glenn jackman's advice to double-quote the $@
inside the script (or omit the in "$@"
part altogether).
Also: xargs -d
is a GNU extension, which, for instance, won't work on FreeBSD/macOS. To make it work there, see @glenn jackman's xargs -0
-based solution.
Note that I'm using printf
rather than echo
to ensure that the \n
instances in the string are interpreted as newlines in all Bourne-like shells:
In bash
and ksh
[1], echo
defaults to NOT interpreting \
-based escape sequences (you have to use -e
to achieve that) - unlike in zsh
and strictly POSIX-compliant shells such as dash
.
Therefore, printf
is the more portable choice.
[1] According to the manual, ksh
's echo
builtin exhibits the same behavior as the host platform's external echo
utility; while this may vary across platforms, the Linux and BSD/macOS implementations do not interpret \
escape sequences by default.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With