Parece que a maneira canônica de fazer isso em 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 eu 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. Neste caso, o comportamento de uma linha é o que eu prefiro de qualquer maneira, então bônus duplo em 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.
Apesar de não funcionar no meu caso, agora aprendi que muitas ferramentas suportam o encerramento de linhas com null (
em vez de %code% , o que facilita muito isso quando se lida com, digamos, arquivo nomes, que são fontes comuns dessas situações: newline (\n)
0)
find / -name '*.config' -print0 | xargs -0 md5
alimenta uma lista de nomes de arquivos completos como argumentos para md5 sem qualquer globbing ou interpolação ou qualquer outra coisa. Isso leva à solução não integrada
tr "\n" "unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
0" <file | xargs -0 cmd
embora isso, também, ignore linhas vazias, embora capture linhas que possuem apenas espaços em branco.