Sembra che il modo canonico per farlo bash
sia qualcosa di simile
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
o, se la tua versione di bash ha mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
L'unica differenza che posso trovare tra il mapfile e il ciclo while-read rispetto al one-liner
(set -f; IFS=$'\n'; cmd $(<file))
è che il primo convertirà una riga vuota in un argomento vuoto, mentre il one-liner ignorerà una riga vuota. In questo caso, il comportamento con una sola linea è quello che preferirei comunque, quindi doppio vantaggio in quanto compatto.
Vorrei usare IFS=$'\n' cmd $(<file)
ma non funziona, perché $(<file)
viene interpretato per formare la riga di comando prima che abbia IFS=$'\n'
effetto.
Anche se non funziona nel mio caso, ora ho imparato che molti strumenti supportano le linee di terminazione null (\000)
invece di newline (\n)
ciò che rende molto più facile questo quando si tratta, per esempio, di nomi di file, che sono fonti comuni di queste situazioni :
find / -name '*.config' -print0 | xargs -0 md5
fornisce un elenco di nomi di file completi come argomenti a md5 senza alterazioni, interpolazioni o altro. Questo porta alla soluzione non integrata
tr "\n" "\000" <file | xargs -0 cmd
sebbene anche questo ignori le linee vuote, sebbene catturi le linee che hanno solo spazi bianchi.