Quando você executa um pipeline, cada elemento separado por pipe é executado em seu próprio processo. Atribuições variáveis só entram em vigor em seu próprio processo. Sob ksh e zsh, o último elemento do pipeline é executado no shell original; sob outras shells como o bash, cada elemento do pipeline é executado em sua própria subshell e o shell original apenas espera que todos eles terminem.
$ bash -c 'GROUPSTATUS=foo; echo GROUPSTATUS is $GROUPSTATUS'
GROUPSTATUS is foo
$ bash -c 'GROUPSTATUS=foo | :; echo GROUPSTATUS is $GROUPSTATUS'
GROUPSTATUS is
No seu caso, uma vez que você só se importa com todos os comandos seguintes, você pode aumentar o fluxo de status.
{ tar -cf - my_folder 2>&1 1>&3 | grep -v "Removing leading" 1>&2;
! ((PIPESTATUS[0])); } 3>&1 |
gzip --rsyncable > my_file.tar.gz;
if ((PIPESTATUS[0] || PIPESTATUS[1])); then rm my_file.tar.gz; fi
Se você deseja obter mais de 8 bits de informação do lado esquerdo de um pipe, pode escrever para outro descritor de arquivo. Aqui está um exemplo de prova de princípio:
{ { tar …; echo $? >&4; } | …; } | { gzip …; echo $? >&4; } \
4>&1 | ! grep -vxc '0'
Depois de obter os dados na saída padrão, você poderá alimentá-los em uma variável do shell usando a substituição de comandos, ou seja, $(…)
. A substituição de comando lê a saída padrão do comando, portanto, se você também quis imprimir as coisas na saída padrão do script, elas precisam passar temporariamente por outro descritor de arquivo. O snippet a seguir usa o fd 3 para coisas que eventualmente vão para o stdout do script e o fd 4 para itens capturados em $statuses
.
statuses=$({ { tar -v … >&3; echo tar $? >&4; } | …; } |
{ gzip …; echo gzip $? >&4; } 4>&1) 3>&1
Se você precisa capturar a saída de diferentes comandos em diferentes variáveis, eu acho que não existe um caminho direto mesmo em shells “avançados” como bash, ksh ou zsh. Aqui estão algumas soluções alternativas:
- Use arquivos temporários.
- Use um único fluxo de saída, por exemplo, um prefixo em cada linha para indicar sua origem e filtrar no nível superior.
- Use uma linguagem mais avançada, como Perl ou Python.