Vorrang von stdin und stdout-Umleitung in Bash

9

Meine Frage ist über die Umleitung Vorrang ist Bash. Angenommen, Sie haben einen Befehl:

cmd1 < cmd2 > cmd3

Würde es übersetzen in:

(cmd1 < cmd2) > cmd3

Oder

cmd1 < (cmd2 > cmd3)

Deepak Mittal
quelle

Antworten:

11

Der POSIX-Standard legt fest, dass die Shell-Umleitung von links nach rechts erfolgt. Das heißt, die Reihenfolge ist wichtig:

Das Konstrukt 2>&1wird häufig verwendet, um Standardfehler in dieselbe Datei wie die Standardausgabe umzuleiten. Da die Umleitungen von Anfang bis Ende stattfinden, ist die Reihenfolge der Umleitungen von Bedeutung. Zum Beispiel:

ls > foo 2>&1

Leitet sowohl die Standardausgabe als auch den Standardfehler in die Datei foo. Jedoch:

ls 2>&1 > foo

Leitet nur die Standardausgabe in die Datei, fooda der Standardfehler als Standardausgabe dupliziert wurde, bevor die Standardausgabe in die Datei geleitet wurde foo.

bash arbeitet in Übereinstimmung mit diesem Teil der Norm:

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

Wie für Rohrleitungen:

Da die Pipeline-Zuweisung von Standardeingabe oder Standardausgabe oder beidem vor der Umleitung erfolgt, kann sie durch Umleitung geändert werden. Zum Beispiel:

$ command1 2>&1 | command2

sendet sowohl die Standardausgabe als auch den Standardfehler von command1an die Standardeingabe von command2.

Matt Eckert
quelle
Dies setzt voraus, dass die Bash-Shell POSIX-kompatibel ist.
fpmurphy
1
Ich verstehe es nicht. Da Sie sagten, die Reihenfolge sei von links nach rechts, sollte dies nicht ls > foo 2>&1bedeuten, stdout nach foo umzuleiten und dann stderr nach stdout umzuleiten. Das sollte also nicht funktionieren. Ebenso sollte der zweite Befehl funktionieren. Was fehlt mir hier?
Deepak Mittal
1
@fpmurphy bashist in der Regel POSIX - konform, außer in den Situationen hier skizzierten , wo das bashStandardverhalten unterscheidet. Um die bashKonformität zu verbessern, können Sie die --posixOption verwenden.
Matt Eckert
@dpacmittal Das erste Beispiel ls > foo 2>&1funktioniert folgendermaßen: Zuerst wird die Standardausgabe umgeleitet foo, dann wird der Standardfehler zur Standardausgabe umgeleitet, die jetzt die Datei ist foo. Das zweite Beispiel ls 2>&1 > foofunktioniert folgendermaßen: Standardfehler werden zur Standardausgabe umgeleitet, bevor die Standardausgabe zu umgeleitet wird foo, sodass Standardfehler lokal wiedergegeben werden, anstatt an die Datei weitergeleitet zu werden.
Matt Eckert
4
@dpacmittal .. re ls 2>&1 >foo vielleicht kannst du dir das so vorstellen . stderr von 'ls' wird zu stdout umgeleitet. Das wird passieren! Es wird dorthin gehen, wo stdout wird derzeit , unabhängig von etwaigen weiteren Richtlinien in Bezug auf die Standardausgabe gehen zugewiesen .. (weil dies seine ist Ansaug- / erste Richtlinie ) .. Dann entlang einer anderen Richtlinie kommen , die besagt , dass stdout „foo“ gehen, und es ist ... Denken sie daran: stderr ist nicht umgewandelte in eigentlich immer stdout .. es geht nur, wo stdout wurde zum Zeitpunkt der Richtlinie zugeordnet. (zB das Terminal)
Peter.O
4

Ich denke auch nicht. Ein Klammerpaar bedeutet eine Unterschale. In diesem Fall wird jedoch aufgrund der Umleitung keine Unter-Shell gestartet. Bash füttert einfach cmd2in stdin und füttert stdout in cmd3.

Ich denke, meinst du so etwas cmd1 | cmd2 | cmd3? Weil Ihre cmd2und cmd3normalerweise normale Dateien anstelle von "cmds" sind.

MetroWind
quelle