netcat shouldn't affect the data sent through it, so I'll skip that and
focus on just piping to xargs.
Here:
echo "aa 'bb cc'" | xargs
the shell removes one set of quotes, sending the string aa 'bb cc'
to xargs. xargs by default takes quoted strings as single elements (removing the quotes), passing the strings aa
and bb cc
to the command it runs.
Here, on the other hand:
echo "aa \'bb cc\'" | xargs
the shell again strips one set of quotes, leaving aa \'bb cc\'
. Single quotes (with or without backslashes) are not special within double quotes. Double quotes within double quotes would need to be escaped, though.
xargs sees that string, does its own quote removal, but since the quotes are escaped now, it just strips the backslashes and splits on whitespace. Leaving three strings: aa
, 'bb
and cc'
. Which is what you saw.
Usually, we want the opposite: to avoid having xargs handle quotes since they might be parts of a file name. So you see five dozen questions here recommending xargs -0
or xargs -d'\n'
instead. But if you want xargs to handle quoted strings, you need to send the quotes to it unescaped.
Another issue is that your test script uses $*
. Without quotes, that will split all arguments on whitespace and perform globbing on the resulting words. (With quotes, it will result in the concatenation of the arguments as a single string.) You almost always want to use "$@"
instead. Or here just:
for i do
echo "$i"
done
or even:
printf '%s\n' "$@"
So, check the escaping of the quotes and use "$@"
instead of $*
.
$ cat args.sh
for x in "$@" ; do echo ":$x" ; done
$ echo "aa 'bb cc' \"dd ee\""
aa 'bb cc' "dd ee"
$ echo "aa 'bb cc' \"dd ee\"" | xargs ./args.sh
:aa
:bb cc
:dd ee
xargs
should take quoted strings as single elements, and remove the quotes, soecho "aa 'bb cc'" | xargs
should havexargs
pass on the stringsaa
andbb cc
. Using$*
splits the latter. But I can't see how the quotes are left remaining in what your shell script sees. – ilkkachu Apr 20 '17 at 12:46nc
at the other end (or even better, skip the nc and try to reproduce the issue with directly inputting toxargs
). Because in the above, you've both quoted and escaped the single-quotes, so xargs sees them escaped and doesn't consider them specially... – ilkkachu Apr 20 '17 at 12:55"$*"
and all should be fine – Valentin Bajrami Apr 20 '17 at 13:11"$*"
will result in all the arguments concatenated to a single string, you might as well remove the loop, then – ilkkachu Apr 20 '17 at 13:57