xargs espera un formato de entrada muy especial donde los argumentos están delimitados por espacios en blanco o nuevas líneas (a veces otras formas de espacios en blanco verticales, a veces dependientes de la configuración regional actual), y donde se pueden usar comillas simples, comillas dobles y barras invertidas para escapar de ellas (pero en una forma diferente camino de las comillas).
-l1no es pasar una línea de entrada como un solo argumento mkdir, sino llamar a una mkdirinvocación para cada línea de entrada, pero con palabras en esa línea aún separadas como argumentos diferentes para mkdir.
La implementación de GNU xargsagregó una -0opción hace décadas para aceptar entradas delimitadas por NUL. Esa es la forma más obvia de separar palabras que terminarán siendo argumentos para un comando porque el carácter NUL resulta ser el único carácter que no puede aparecer en un argumento de comando o nombre de archivo (el formato de lista elegido que coloca un archivo por línea no puede representar todos los nombres de archivo posibles ya que no permite una nueva línea en un nombre de archivo).
Eso -0ha sido copiado por varias otras xargsimplementaciones, pero no todas.
Con los que puedes hacer:
<file tr '\n' '\0' | xargs -0 mkdir -p --
Eso requerirá la mkdirmenor cantidad de veces posible con tantos argumentos como sea posible.
Pero tenga en cuenta que si fileestá vacío, mkdirtodavía se ejecutará y obtendrá un error de sintaxis mkdirdebido al argumento que falta. GNU xargsagregó una -ropción para lo que ha sido copiado por algunas otras implementaciones.
GNU xargstambién agregó (más adelante) una -dopción para poder especificar delimitadores arbitrarios, pero no creo que ninguna otra implementación lo haya copiado. Con GNU xargs, la mejor manera es con:
xargs -rd '\n' -a file mkdir -p --
Al pasar el archivo con -a(también una extensión GNU) en lugar de stdin, eso significa que mkdirse preserva el stdin.
POSIXY, necesitaría postprocesar la entrada para ponerla en el formato esperado por xargs. Podrías hacerlo por ejemplo con:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --
Donde encerramos cada línea entre comillas dobles y escapamos de cada una "como "\""antes de alimentar a xargs.
Pero cuidado con las posibles limitaciones:
- el error cuando el archivo está vacío ya mencionado anteriormente
- puede fallar con algunas implementaciones (incluso de
sed) si el contenido de fileno es texto válido en la configuración regional actual. Si filecontiene nombres de archivos que codifican en más de un conjunto de caracteres diferente, o un conjunto de caracteres diferente al de la configuración regional, puede corregir la configuración regional en C, lo que debería ayudar.
- Algunas
xargsimplementaciones tienen límites ridículamente bajos en la longitud máxima de un argumento (puede ser tan bajo como 255 bytes).
Para evitar el error de sintaxis en el error de entrada vacía , puede escribir:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh
-dopción.