Parece que a maneira canônica de fazer isso bash
é algo como
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
ou, se sua versão do bash tiver mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
A única diferença que posso encontrar entre o mapfile e o loop while-read versus o one-liner
(set -f; IFS=$'\n'; cmd $(<file))
é que o primeiro converterá uma linha em branco em um argumento vazio, enquanto o one-liner ignorará uma linha em branco. Nesse caso, o comportamento de uma linha é o que eu preferiria de qualquer maneira, portanto, um bônus duplo por ser compacto.
Eu usaria, IFS=$'\n' cmd $(<file)
mas não funciona, porque $(<file)
é interpretado para formar a linha de comando antes de IFS=$'\n'
entrar em vigor.
Embora não funcione no meu caso, agora aprendi que muitas ferramentas suportam linhas de terminação, em null (\000)
vez das newline (\n)
quais facilitam muito isso quando se lida com, por exemplo, nomes de arquivos, fontes comuns dessas situações :
find / -name '*.config' -print0 | xargs -0 md5
alimenta uma lista de nomes de arquivos totalmente qualificados como argumentos para o md5 sem globbing, interpolação ou qualquer outra coisa. Isso leva à solução não integrada
tr "\n" "\000" <file | xargs -0 cmd
embora isso também ignore linhas vazias, mas captura linhas que possuem apenas espaço em branco.