Precedenza di reindirizzamento stdin e stdout in Bash


9

La mia domanda è sulla precedenza di reindirizzamento è bash. Supponiamo di avere un comando:

cmd1 < cmd2 > cmd3

Si tradurrebbe in:

(cmd1 < cmd2) > cmd3

O

cmd1 < (cmd2 > cmd3)

Risposte:


11

Lo standard POSIX specifica che il reindirizzamento della shell è da sinistra a destra; cioè, l'ordine è significativo:

Il costrutto 2>&1viene spesso utilizzato per reindirizzare l'errore standard sullo stesso file dell'output standard. Poiché i reindirizzamenti avvengono dall'inizio alla fine, l'ordine dei reindirizzamenti è significativo. Per esempio:

ls > foo 2>&1

dirige sia l'output standard sia l'errore standard nel file foo. Però:

ls 2>&1 > foo

dirige l'output standard su file solo fooperché l'errore standard è stato duplicato come output standard prima che l'output standard fosse indirizzato al file foo.

bash opera in conformità con questa parte della norma:

$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$ 

Per quanto riguarda le tubazioni:

Poiché l'assegnazione della pipeline di input standard o output standard o entrambi avviene prima del reindirizzamento, può essere modificata mediante reindirizzamento. Per esempio:

$ command1 2>&1 | command2

invia sia l'output standard sia l'errore command1standard dell'input standard di command2.


Ciò presuppone che la shell Bash sia compatibile con POSIX.
fpmurphy,

1
Non lo capisco. Dal momento che hai detto che l'ordine è da sinistra a destra, non dovrebbe ls > foo 2>&1significare reindirizzare stdout a foo quindi reindirizzare stderr a stdout. Quindi questo non dovrebbe funzionare. Allo stesso modo il secondo comando dovrebbe funzionare. Cosa mi sto perdendo qui?
Deepak Mittal,

1
@fpmurphy bashè generalmente conforme a POSIX, tranne nelle situazioni descritte qui , in cui il bashcomportamento predefinito differisce. Per rendere bashpiù conforme, è possibile utilizzare l' --posixopzione.
Matt Eckert,

@dpacmittal Il primo esempio ls > foo 2>&1funziona in questo modo: innanzitutto, l'output standard viene reindirizzato a foo, quindi l'errore standard viene reindirizzato all'output standard, che ora è il file foo. Il secondo esempio ls 2>&1 > foofunziona in questo modo: l'errore standard viene reindirizzato all'output standard prima che venga reindirizzato all'output standard foo, quindi l'errore standard viene ripetuto localmente anziché essere indirizzato al file.
Matt Eckert,

4
@dpacmittal .. ls 2>&1 >foo forse potresti pensarci così. stderr da 'ls' viene reindirizzato a stdout. Questo accadrà! Andrà a dove stdout è attualmente assegnato, indipendentemente da ulteriori direttive relative a stdout .. (perché questa è la sua prima / prima direttiva ) .. Poi arriva un'altra direttiva che dice che stdout andrà a "pippo", e lo fa ... Ricorda: stderr non viene trasmutato in realtà diventando stdout .. Va solo a dove stdout è stato assegnato al momento della direttiva. (es. il terminal)
Peter.O

4

Nemmeno io. Una coppia di parentesi indica una sotto-shell. Ma in questo caso, nessuna shell secondaria verrà avviata a causa del reindirizzamento. Bash si nutre semplicemente di cmd2stdin e di stdout cmd3.

Sto pensando, vuoi dire qualcosa del genere cmd1 | cmd2 | cmd3? Perché i tuoi cmd2e di cmd3solito sono file normali invece di "cmds".

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.