On dirait que la manière canonique de le faire bash
est quelque chose comme
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
ou, si votre version de bash a mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
La seule différence que je peux trouver entre le mapfile et la boucle en lecture par rapport au one-liner
(set -f; IFS=$'\n'; cmd $(<file))
est que le premier convertira une ligne vide en un argument vide, tandis que le one-liner ignorera une ligne vide. Dans ce cas, le comportement à une ligne est ce que je préférerais de toute façon, donc double bonus sur le fait qu'il soit compact.
J'utiliserais IFS=$'\n' cmd $(<file)
mais cela ne fonctionne pas, car $(<file)
est interprété pour former la ligne de commande avant de IFS=$'\n'
prendre effet.
Bien que cela ne fonctionne pas dans mon cas, j'ai maintenant appris que de nombreux outils prennent en charge les terminaisons de lignes avec lesquelles, au null (\000)
lieu de newline (\n)
cela, cela facilite grandement la gestion, par exemple, des noms de fichiers, qui sont des sources courantes de ces situations. :
find / -name '*.config' -print0 | xargs -0 md5
alimente une liste de noms de fichiers pleinement qualifiés en tant qu'arguments à md5 sans globalisation ou interpolation ou quoi que ce soit. Cela conduit à la solution non intégrée
tr "\n" "\000" <file | xargs -0 cmd
bien que cela, aussi, ignore les lignes vides, bien qu'il capture les lignes qui n'ont que des espaces.