Assuming test.sh
is something like
echo arg: "$@"
As already pointed out, you need to escape -d '\n'
and it should be noted that this is a GNU extension. It basically is a shortcut to the posix compatible tr '\n' '\0' | xargs -0
But xargs
is more versatile and subtle in many cases. It can be used to massage parameters very precisely and can be well illustrated using sh
printf
. cat -A
is used to clearly show the difference.
In a nutshell, xargs
splits on whitespace and it treats newlines specially.
To only split on newlines, use -d '\n'
or tr '\n' '\0'
or use something like sed
to escape spaces and tabs.
Process invoked once, with three arguments.
printf '%s\n' "ac s" "bc s" "cc s" |
xargs -d '\n' sh -c 'printf "%s\t" arg: "$@"'';printf "\n"' xargs-example |
cat -A
arg:^Iac s^Ibc s^Icc s^I$
Process invoked once, with 6 arguments.
printf '%s\n' "ac s" "bc s" "cc s" |
xargs sh -c 'printf "%s\t" arg: "$@"'';printf "\n"' xargs-example |
cat -A
arg:^Iac^Is^Ibc^Is^Icc^Is^I$
Process invoked twice, with 4 and 2 arguments respectively
printf '%s\n' "ac s" "bc s" "cc s" |
xargs -L2 sh -c 'printf "%s\t" arg: "$@"'';printf "\n"' xargs-example |
cat -A
arg:^Iac^Is^Ibc^Is^I$
arg:^Icc^Is^I$
Process invoked twice, with 2 and 1 arguments respectively.
printf '%s\n' "ac s" "bc s" "cc s" |
xargs -d '\n' -L2 sh -c 'printf "%s\t" arg: "$@"'';printf "\n"' xargs-example |
cat -A
arg:^Iac s^Ibc s^I$
arg:^Icc s^I$
This may seem a bit complicated but it allows you to use tabs and newlines to control xargs
where tabs become argument separators and newlines control which arguments each process is invoked with, ie.
Process invoked twice, with 3 and 1 argument respectively
printf '%s\n' ac$'\t's "bc s" "cc s" |
sed '
# escape spaces
s@ @\\ @g
' |
xargs -L2 sh -c 'printf "%s\t" arg: "$@"'';printf "\n"' xargs-example |
cat -A
arg:^Iac^Is^Ibc s^I$
arg:^Icc s^I$