Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Created October 18, 2024 03:29
Show Gist options
  • Save x-yuri/44aa8ccfc91ef2a9dc7147cade9de684 to your computer and use it in GitHub Desktop.
Save x-yuri/44aa8ccfc91ef2a9dc7147cade9de684 to your computer and use it in GitHub Desktop.
xargs

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment