tl;dr By default quotes and backslash quote blanks (spaces), and only backslash can quote newlines. With -d
and -0
, all of those are not special (unless one of those is passed with -d
). With -I
the separator is a newline and it uses one argument per invocation. Quotes and backslash are stripped (1). Quotes must be balanced (2). Use along with -d\\n
to avoid (1) and (2).
By default single, double quotes and backslash quote blanks (e.g. spaces):
$ echo "'a b' c" | xargs -t
echo 'a b' c
a b c
$ echo '"a b" c' | xargs -t
echo 'a b' c
a b c
$ echo 'a\ b c' | xargs -t
echo 'a b' c
a b c
Only backslash can quote newlines:
$ echo "'a"$'\n'"b'" | xargs -t
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
$ echo $'"a\nb"' | xargs -t
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$ echo $'a\\\nb' | xargs -t
echo 'a'$'\n''b'
a
b
With -d
newlines, single, double quotes, and backslash are not treated specially:
$ echo 'abc' | xargs -tdb
echo a 'c'$'\n'
a c
$ echo "'" | xargs -tdb
echo ''\'''$'\n'
'
$ echo '"' | xargs -tdb
echo '"'$'\n'
"
$ echo '\' | xargs -tdb
echo '\'$'\n'
\
With -0
the separator is \0
:
$ perl -e 'print "a\0b"' | xargs -t0
echo a b
a b
Single, double quotes and backslash aren't special:
$ echo "a'b" | xargs -t0
echo 'a'\''b'$'\n'
a'b
$ echo 'a"b' | xargs -t0
echo 'a"b'$'\n'
a"b
$ echo 'a\b' | xargs -t0
echo 'a\b'$'\n'
a\b
-L
treats trailing blanks specially, for -L
$'a \nb'
is one line:
$ echo $'a\nb' | xargs -tL1
echo a
a
echo b
b
$ echo $'a \nb' | xargs -tL1
echo a b
a b
With -I
the separator is a newline and it uses one argument per invocation:
$ echo $'a\nb' | xargs -tI{} echo {}
echo a
a
echo b
b
-I
implies -L1
, for which trailing blanks are special, but that's not the case with -I
:
$ echo $'a \nb' | xargs -tI{} echo {}
echo 'a '
a
echo b
b
Well, technically this doesn't contradict -L1
. -L1
imposes a limit on the number of lines used for an invocation, and -I
uses only one argument from possibly more than one line. And for -I
any blanks (spaces) aren't special.
Single, double quotes and backslash are stripped:
$ echo "'a b'" | xargs -tI{} echo {}
echo 'a b'
a b
$ echo '"a b"' | xargs -tI{} echo {}
echo 'a b'
a b
$ echo 'a\b' | xargs -tI{} echo {}
echo ab
ab
But quotes must be balanced:
$ echo $'"' | xargs -tI{} echo {}
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$ echo "'" | xargs -tI{} echo {}
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
Use along with -d\\n
to avoid that:
$ echo \"$'\n'\'$'\n'\\ | xargs -tI{} echo {}
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$ echo \"$'\n'\'$'\n'\\ | xargs -tI{} -d\\n echo {}
echo '"'
"
echo "'"
'
echo '\'
\
Blanks aren't special:
$ echo 'a b' | xargs -tI{} echo {}
echo 'a b'
a b