Não sabemos o tamanho da saída de cmd1
, mas os canais têm um tamanho de buffer limitado . Uma vez que essa quantidade de dados tenha sido gravada no pipe, qualquer gravação subsequente será bloqueada até que alguém leia o canal (tipo de sua solução com falha 3).
Você deve usar um mecanismo que garanta não bloquear. Para dados muito grandes, use um arquivo temporário. Senão, se você puder pagar por manter os dados na memória (essa era a ideia, afinal, com pipes), use isto:
result=$(cmd1) && cmd2 < <(printf '%s' "$result")
unset result
Aqui, o resultado de cmd1
é armazenado na variável result
. Se cmd1
for bem-sucedida, cmd2
será executado e será alimentado com os dados em result
. Finalmente, result
não está configurado para liberar a memória associada.
Nota: antigamente, eu usava uma string aqui ( <<< "$result"
) para alimentar cmd2
com dados, mas Stéphane Chazelas observou que bash
criaria um arquivo temporário, o que você não deseja.
Respostas a perguntas no comentário:
-
Sim, os comandos podem ser encadeados ad libitum :
result=$(cmd1) \ && result=$(cmd2 < <(printf '%s' "$result")) \ && result=$(cmd3 < <(printf '%s' "$result")) \ ... && cmdN < <(printf '%s' "$result") unset result
-
Não, a solução acima não é adequada para dados binários porque:
- Substituição de comando
$(...)
come todas as novas linhas finais. - O comportamento não é especificado para caracteres NUL (
) no resultado de uma substituição de comando (por exemplo, o Bash os descartaria).base64
- Substituição de comando
-
Sim, para contornar todos esses problemas com dados binários, você pode usar um codificador como
uuencode
(ou>(...)
, ou um codificador caseiro que cuida apenas dos caracteres NUL e das novas linhas iniciais):result=$(cmd1 > >(base64)) && cmd2 < <(printf '%s' "$result" | base64 -d) unset result
Aqui, tive que usar uma substituição de processo (
cmd1
) para manter o valor de saída %code% intacto.
Dito isso, mais uma vez parece ser um incômodo apenas garantir que os dados não sejam gravados no disco. Um arquivo temporário intermediário é uma solução melhor. Veja a resposta de Stéphane que aborda a maioria de suas preocupações sobre isso.