Piping sia stdout che stderr in bash?


156

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

Qual è il modo più semplice per ottenere la stessa cosa, ma invece eseguire il piping a un altro comando?

Ad esempio, in questa riga:

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

Vorrei che grep corrispondesse ai contenuti sia in stdout che in stderr (in effetti, combinali in un unico stream).

Nota : questa domanda è relativa al piping, non al reindirizzamento, quindi non è un duplicato della domanda su cui è attualmente contrassegnato come duplicato.


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

4
@triplee Non è un duplicato esatto, vero? Pipe vs. reindirizzamento al file?
Benjamin W.,

@BenjaminW Esiste almeno una risposta che risolve entrambi gli scenari, sebbene non sia la risposta accettata. Questa è una domanda abbastanza comune, quindi potremmo probabilmente trovare un duplicato migliore o chiedere a un moderatore di unirli o, nel peggiore dei casi, creare un canonico completamente nuovo per questo argomento. Se trovi un duplicato migliore, sicuramente lo proponi. Grazie in anticipo.
Tripleee,

12
@tripleee Risolve, sì, ma nessuna delle risposte usa la |&scorciatoia, che penso sia di gran lunga la soluzione più conveniente per "reindirizzare sia stdout che stderr su una pipe".
Benjamin W.,

3
Questo non è un duplicato della domanda collegata e non era chiaro che la risposta di Marko avesse fatto quello che volevo. Inoltre, non menziona | &. Votazione per riaprire.
Martin Bonner supporta Monica

Risposte:


163

(Si noti che viene &>>file aggiunto a un file mentre &>si reindirizzerebbe e sovrascriverebbe un file esistente in precedenza.)

Per combinare stdoute stderrsi sarebbe reindirizzare il secondo al primo utilizzo 2>&1. Questo reindirizza stderr (descrittore di file 2) su stdout (descrittore di file 1), ad esempio:

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

stdoutva a stdout, stderrva a stderr. grepvede solo stdout, quindi stderrstampa sul terminale.

D'altro canto:

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

Dopo aver scritto sia su stdout che su stderr, 2>&1reindirizza stderr su stdout e grepvede entrambe le stringhe su stdin, quindi filtra entrambe.

Puoi leggere di più sul reindirizzamento qui .

Per quanto riguarda il tuo esempio (POSIX):

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

oppure, usando >=bash-4:

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

Grazie per il chiarimento su &>>. Ho corretto la mia domanda.
Andrew Ferrier,

18
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 lo specifico bash |&invece di 2>&1 |.
Adrian Frühwirth,

13
Nota a |&margine sul collegamento proposto da @ AdrianFrühwirth per i futuri lettori: questa funzione è supportata solo con la bashversione 4+. Se usi 3 o meno, devi attenersi a 2>&1 |.
Tomocafe,

3
Il reindirizzamento di Bash è molto ben spiegato qui . @ AdrianFrühwirth ha fatto un buon lavoro, il collegamento incollato va ancora oltre. A volte, vorrei che la documentazione ufficiale di Bash fosse così buona.
David Andreoletti,

112

Bash ha una scorciatoia per 2>&1 |, cioè |&, che convoglia sia stdout che stderr (vedi il manuale ):

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

Questo è stato introdotto in Bash 4.0, vedere le note di rilascio .


Grazie per averlo aggiunto per completezza. Terrò corretta l'altra risposta poiché molte persone usano ancora bash pre-4.0. Ma questo è utile
Andrew Ferrier,

9
In particolare forse, il Bash fornito su macOS è troppo vecchio per supportarlo.
Flimm,

@Flimm ma lo zsh non lo è
Trenton,

1
Dato che ksh usa | & per coproc, questa sembra una cattiva scelta per una scorciatoia non necessaria. Odio vedere le righe con una pila di duplicati e reindirizzamenti tanto quanto il prossimo, ma c'è qualcosa da dire per essere esplicito .... e mi scuso che questo commento non aggiunga molto. Volevo solo esprimere disgusto per la stenografia senza sottovalutare una risposta effettivamente utile, perché è bello che la gente lo veda. Non lo sapevo, quindi grazie per avermi informato.
Paul Hodges,

@PaulHodges Sono d'accordo sul fatto che non sia portatile - mi piace principalmente usarlo per sessioni interattive di Bash per evitare di scrivere troppo.
Benjamin W.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.