Priorité de la redirection stdin et stdout dans Bash

9

Ma question concerne la priorité de redirection est bash. Supposons que vous ayez une commande:

cmd1 < cmd2 > cmd3

Cela se traduirait-il par:

(cmd1 < cmd2) > cmd3

Ou

cmd1 < (cmd2 > cmd3)

Deepak Mittal
la source

Réponses:

11

La norme POSIX spécifie que la redirection du shell se fait de gauche à droite; autrement dit, l'ordre est important:

La construction 2>&1est souvent utilisée pour rediriger l'erreur standard vers le même fichier que la sortie standard. Étant donné que les redirections ont lieu du début à la fin, l'ordre des redirections est significatif. Par exemple:

ls > foo 2>&1

dirige la sortie standard et l'erreur standard vers le fichier foo. Toutefois:

ls 2>&1 > foo

dirige uniquement la sortie standard vers le fichier foocar l'erreur standard a été dupliquée en tant que sortie standard avant que la sortie standard ne soit dirigée vers le fichier foo.

bash fonctionne conformément à cette partie de la norme:

$ 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
$ 

Quant à la tuyauterie:

Étant donné que l'affectation de pipeline d'entrée standard ou de sortie standard ou les deux a lieu avant la redirection, elle peut être modifiée par redirection. Par exemple:

$ command1 2>&1 | command2

envoie à la fois la sortie standard et l'erreur standard de command1à l'entrée standard de command2.

Matt Eckert
la source
Cela suppose que le shell Bash est compatible POSIX.
fpmurphy
1
Je ne comprends pas. Puisque vous avez dit que l'ordre allait de gauche à droite, cela ne devrait pas ls > foo 2>&1signifier rediriger stdout vers foo puis rediriger stderr vers stdout. Cela ne devrait donc pas fonctionner. De même, la deuxième commande devrait fonctionner. Qu'est-ce que j'oublie ici?
Deepak Mittal
1
@fpmurphy bashest généralement compatible POSIX, sauf dans les situations décrites ici , où le bashcomportement par défaut diffère. Pour rendre bashplus conforme, vous pouvez utiliser l' --posixoption.
Matt Eckert
@dpacmittal Le premier exemple,, ls > foo 2>&1fonctionne comme ceci: d'abord, la sortie standard est redirigée vers foo, puis, l'erreur standard est redirigée vers la sortie standard, qui est maintenant le fichier foo. Le deuxième exemple ls 2>&1 > foo,, fonctionne comme ceci: l'erreur standard est redirigée vers la sortie standard avant que la sortie standard ne soit redirigée foo, donc l'erreur standard est répercutée localement au lieu d'être dirigée vers le fichier.
Matt Eckert
4
@dpacmittal .. re ls 2>&1 >foo peut-être que vous pouvez penser comme ça. stderr de 'ls' est redirigé vers stdout. Cela arrivera! Il ira là où stdout est actuellement assigné pour aller, indépendamment de toute autre directive relative à stdout .. (parce que c'est sa première / première directive ) .. Ensuite vient une autre directive qui dit que stdout ira à "foo", et il le fait ... Rappelez-vous: stderr n'est pas transmuté en devenant réellement stdout .. Il va juste là où stdout a été assigné au moment de la directive. (par exemple, le terminal)
Peter
4

Je suppose que non plus. Une paire de parenthèses signifie un sous-shell. Mais dans ce cas, aucun sous-shell ne sera démarré à cause de la redirection. Bash alimente simplement cmd2stdin et stdout cmd3.

Je pense, tu veux dire quelque chose comme cmd1 | cmd2 | cmd3? Parce que vos fichiers cmd2et cmd3sont généralement normaux au lieu de "cmds".

MetroWind
la source