xargs attend un format d'entrée très spécial où les arguments sont délimités par des espaces ou des retours à la ligne (parfois d'autres formes d'espaces verticaux, parfois dépendants des paramètres régionaux actuels), et où des guillemets simples, des guillemets doubles et une barre oblique inversée peuvent être utilisés pour les échapper (mais dans un autre des citations shell).
-l1ne consiste pas à passer une ligne d'entrée en tant qu'argument unique à mkdir, mais à appeler une mkdirinvocation pour chaque ligne d'entrée mais avec des mots sur cette ligne toujours séparés en tant qu'arguments différents mkdir.
L'implémentation GNU a xargsajouté une -0option il y a des décennies pour accepter les entrées délimitées par NUL. C'est le moyen le plus évident de séparer les mots qui finiront par être des arguments d'une commande car le caractère NUL se trouve être le seul caractère qui ne peut pas apparaître dans un argument de commande ou un nom de fichier (le format de liste choisi qui place un fichier par ligne ne peut pas représenter tous les noms de fichiers possibles car il n'autorise pas la nouvelle ligne dans un nom de fichier).
Cela -0a été copié par plusieurs autres xargsimplémentations mais pas toutes.
Avec ceux que vous pouvez faire:
<file tr '\n' '\0' | xargs -0 mkdir -p --
Cela appellera mkdirle moins de fois possible avec autant d'arguments que possible.
Mais notez que si fileest vide, mkdirsera toujours exécuté et vous obtiendrez une erreur de syntaxe en mkdirraison de l'argument manquant. GNU a xargsajouté une -roption pour celle qui a été copiée par quelques autres implémentations.
GNU a xargségalement ajouté (plus tard) une -doption pour pouvoir spécifier des délimiteurs arbitraires, mais je pense qu'aucune autre implémentation ne l'a copiée. Avec GNU xargs, le meilleur moyen est de:
xargs -rd '\n' -a file mkdir -p --
En passant le fichier avec -a(également une extension GNU) au lieu de stdin, cela signifie que mkdirle stdin est préservé.
POSIX, vous devez post-traiter l'entrée pour la mettre au format attendu par xargs. Vous pouvez le faire par exemple avec:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --
Où nous enfermons chaque ligne entre guillemets doubles et s'échappons "comme "\""avant d'alimenter xargs.
Mais attention aux limitations possibles:
- l'erreur lorsque le fichier est vide déjà mentionné ci-dessus
- il peut échouer avec certaines implémentations (y compris de
sed) si le contenu de filen'est pas du texte valide dans les paramètres régionaux actuels. Si filecontient des noms de fichier codant dans plusieurs jeux de caractères différents, ou un jeu de caractères différent de celui des paramètres régionaux, vous pouvez corriger les paramètres régionaux en C, ce qui devrait vous aider.
- certaines
xargsimplémentations ont des limites ridiculement basses sur la longueur maximale d'un argument (peut être aussi bas que 255 octets).
Pour contourner l' erreur de syntaxe en cas d'erreur d'entrée vide , vous pouvez écrire:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh
-doption.