Você pode efetivamente trocar stdin e stdout com a ajuda de um descritor de arquivo temporário (fd 3 aqui):
cmd 3>&2 2>&1 1>&3- | tr '[:lower:]' '[:upper]'
Isso indica que "aponte o novo fd no local stderr , aponte stderr onde stdout aponta, aponte stdout para onde stderr apontou originalmente "... fácil, certo? :)
Ou, em outras palavras: agora o stderr do cmd
irá percorrer o canal como stdout enquanto o stdout original foi redirecionado para stderr . E o comando tr
fará a conversão de letras maiúsculas.
Atualização: Embora você tenha aceitado a resposta acima, sua lista de desejos incluiu a capacidade de manipular stdout e stderr simultaneamente. Então, vamos tentar resolver isso ... tendo em mente que estamos nos deparando com algumas coisas que eu não faço com frequência!
Uma troca simples de stdout / stderr não fará nada de útil. Com ou sem o swap, você não pode usar dois fluxos diferentes através de um único pipeline. A primeira coisa que vem à mente como alternativa é usar FIFOs (named pipes):
mkfifo /tmp/fifo1 /tmp/fifo2
# run the key command in the background, in a subshell to suppress
# job control messages (e.g. "[1] 12345" and "[1]+ Exit ...")
( cmd > /tmp/fifo1 2> /tmp/fifo2 & )
# concatenate tr/stderr and grep/stdout using process substitution
# (I'm assuming the summary information occurs at the end of rsync output)
cat <(cat /tmp/fifo2 | tr '[:lower:]' '[:upper:]') <(grep ... /tmp/fifo1)
rm -f /tmp/fifo1 /tmp/fifo2
Você poderia realmente colocar tudo isso em uma linha, se assim inclinado!
mkfifo /tmp/fifo1 /tmp/fifo2; (cmd > /tmp/fifo1 2> /tmp/fifo2 &); cat <(cat /tmp/fifo2 | tr '[:lower:]' '[:upper:]') <(grep ... /tmp/fifo1); rm -f /tmp/fifo1 /tmp/fifo2
Meus testes de sanidade estão funcionando bem, então experimente.