exibir STDOUTs antes de STDERR?

9

Sou novo no bash e não posso, para minha vida, descobrir como executar um determinado comando, suponha ./fff e imprima stdouts regulares antes de stderr (estou confuso sobre o significado de mim mesmo)

por exemplo

$ printf "I am a\ndrill\n" > fff; 
$ cat fff nofile fff nofile fff

I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill

precisa ser impresso como:

I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory

Eu entendo que preciso redirecionar minha saída primeiro para um arquivo e, em seguida, anexar o erro ao mesmo arquivo, mas essa é a saída que recebo para

$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see 

I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory
    
por MeOw 14.01.2018 / 23:10

1 resposta

18

Você precisará manter a saída stderr em algum lugar para poder exibi-la no final.

Um arquivo vem à mente:

fff 2> file; cat file >&2

Ou memória (aqui usando sponge de moreutils ):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1 : dentro de {...} descritor de arquivo (fd) 3 pontos para o mesmo recurso que o stdout original (para que possamos usá-lo para restaurar o stdout para fff ).
  • fff <redirs> | sponge <redirs> , fff e sponge foram executados simultaneamente (com <redirs> aplicado independentemente) com o stdout de fff indo para um canal, e a porcentagem de sponge sendo a outra extremidade do canal.
  • 2>&1 : fd 2 de fff (stderr) aponta para a mesma coisa que para 1: o canal neste ponto, portanto, o erro fff vai para sponge através desse canal.
  • >&3 : agora o stdout aponta para o stdout original (redireciona de volta para o que era)
  • 3>&- : fechamos fd 2, o qual fff não precisa
  • sponge acumula sua entrada e apenas a exibe (em seu stdout que foi redirecionado com >&2 para o mesmo recurso que stderr) depois de ter detectado eof em seu stdin (assumido como sendo quando fff termina e já escreveu toda a sua saída em sua stdout).

Se sponge não estiver instalado, você poderá substituí-lo por perl -0777 -pe '' . Com -pe '' , perl lê um registro por vez de sua entrada e grava no stdout. -0777 é o modo slurp no qual o registro (apenas um nesse caso) é a entrada inteira.

    
por 14.01.2018 / 23:15