2013-05-11 8 views
98

Sembra che le versioni più recenti di bash abbiano l'operatore &>, che (se ho capito bene), reindirizza sia stdout che stderr in un file (&>> aggiunge al file invece, come chiarito da Adrian).Piping sia in stdout che in stderr in bash?

Qual è il modo più semplice per ottenere lo stesso risultato, ma eseguire il piping su un altro comando?

Ad esempio, in questa linea:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError 

mi piacerebbe il grep per abbinare il contenuto sia in stdout e stderr (in modo efficace, li hanno combinati in un unico flusso).

Nota: questa domanda sta chiedendo su tubazioni, non reindirizzamento - quindi non è un duplicato della questione è attualmente contrassegnato come un duplicato di.

+0

Vedere la seconda risposta (https://stackoverflow.com/a/637834/1129642) sulla domanda collegata per il modo corretto di reindirizzare sia stdout che stderr. Non c'è bisogno di un'altra domanda. – Marki555

+3

@ triplee Non è un duplicato esatto, vero? Pipe vs. reindirizza al file? –

+0

@BenjaminW C'è almeno una risposta lì che risolve entrambi gli scenari, anche se non è la risposta accettata.Questa è una domanda abbastanza comune, quindi potremmo probabilmente trovare un duplicato migliore o chiedere a un moderatore di unirli o, nel caso peggiore, creare un canone completamente nuovo per questo argomento. Se trovi una persona migliore, la proponi con tutti i mezzi. Grazie in anticipo. – tripleee

risposta

114

(Si noti che &>>fileaccoda ad un file mentre &> sarebbe reindirizzare e sovrascrivere un file precedentemente esistente.)

Per combinare stdout e stderr si sarebbe reindirizzare il secondo al primo utilizzando 2>&1. Questo reindirizza stderr (descrittore di file 2) sullo standard output (descrittore di file 1), ad es .:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std 
stderr 
$ 

stdout va a stdout, stderr va a stderr. grep vede solo stdout, quindi stderr stampa sul terminale.

D'altra parte:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std 
$ 

Dopo aver scritto sia stdout e stderr, 2>&1 reindirizza stderr al stdout e grep vede entrambe le stringhe su stdin, quindi filtra fuori entrambi.

Ulteriori informazioni sul reindirizzamento here.

Per quanto riguarda il vostro esempio (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError 

o, usando >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError 
+0

Grazie per il chiarimento su '& >>'. Ho corretto la mia domanda. –

+14

Ho aggiunto il tuo esempio alla mia risposta, nel caso in cui non fosse ovvio in base ai miei esempi forniti. Come nota a margine, puoi anche usare il carattere '| &' specifico per bash invece di '2> & 1 |'. –

+0

Grazie per il chiarimento. Risposta utile, grazie. –

46

Bash ha una scorciatoia per 2>&1 |, vale a dire |&, che i tubi sia stdout e stderr (vedere la manual):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError 

Questo è stato introdotto in Bash 4.0, vedere lo release notes.

+0

Grazie per aver aggiunto questo per completezza. Continuerò a correggere l'altra risposta visto che molti utenti stanno ancora utilizzando bash pre-4.0. Ma questo è utile. –

+3

In particolare, forse il Bash che viene caricato su macOS è troppo vecchio per supportare questo. – Flimm

+0

@Flimm ma zsh non è – Trenton