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).
-l1
no es pasar una línea de entrada como un solo argumento mkdir
, sino llamar a una mkdir
invocació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 xargs
agregó una -0
opció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 -0
ha sido copiado por varias otras xargs
implementaciones, pero no todas.
Con los que puedes hacer:
<file tr '\n' '\0' | xargs -0 mkdir -p --
Eso requerirá la mkdir
menor cantidad de veces posible con tantos argumentos como sea posible.
Pero tenga en cuenta que si file
está vacío, mkdir
todavía se ejecutará y obtendrá un error de sintaxis mkdir
debido al argumento que falta. GNU xargs
agregó una -r
opción para lo que ha sido copiado por algunas otras implementaciones.
GNU xargs
también agregó (más adelante) una -d
opció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 mkdir
se 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 file
no es texto válido en la configuración regional actual. Si file
contiene 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
xargs
implementaciones 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
-d
opción.