xargs expects a very special input format where arguments are delimited by blanks or newlines (sometimes other forms of vertical whitespace, sometimes dependant on the current locale), and where single quote, double quotes and backslash can be used to escape them (but in a different way from shell quotes).
-l1 is not to pass one line of input as one single argument to
mkdir, but to call one
mkdir invocation for each single line of input but with words on that line still separated out as different arguments to
The GNU implementation of
xargs added a
-0 option decades ago to accept NUL-delimited input. That's the most obvious way to separate words that are going to end up being arguments to a command because the NUL character happens to be the only character that cannot occur in a command argument or file name (your chosen list format which puts one file per line can't represent all possible file names as it doesn't allow a newline in a file name).
-0 has been copied by several other
xargs implementations but not all.
With those you can do:
<file tr '\n' '\0' | xargs -0 mkdir -p --
That will call
mkdir as few times as possible with as many arguments as possible.
But note that if
file is empty,
mkdir will still be run and you'll get a syntax error by
mkdir because of the missing argument. GNU
xargs added a
-r option for that which has been copied by a few other implementations.
xargs also added (later) a
-d option to be able to specify arbitrary delimiters, but I don't think any other implementation copied it. With GNU
xargs, the best way is with:
xargs -rd '\n' -a file mkdir -p --
By passing the file with
-a (also a GNU extension) instead of stdin, that means
mkdir's stdin is preserved.
POSIXly, you'd need to post-process the input to put it in the format expected by
xargs. You could do it for instance with:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --
Where we enclose each line inside double quotes and escape each
"\"" before feeding to xargs.
But beware of possible limitations:
- the error when the file is empty already mentioned above
- it may fail with some implementations (including of
sed) if the content of
file is not valid text in the current locale. If
file contains file names encoding in more than one different charset, or a charset different from the the locale's one, you can fix the locale to C which should help.
xargs implementations have ridiculously low limits on the maximum length of an argument (can be as low as 255 bytes).
To work around the syntax error upon empty input error, you can write:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh