Kolejność przekierowań

29

Nie do końca rozumiem, jak komputer odczytuje to polecenie.

cat file1 file2 1> file.txt 2>&1

Jeśli rozumiem, 2>&1po prostu przekieruj Standard Error na Standard Output.

Zgodnie z tą logiką polecenie brzmi następująco:

  1. łącz pliki file1i file2.

  2. wyślij stdoutz tej operacji do file.txt.

  3. wysłać stderrdo stdout.

  4. koniec?

Nie jestem pewien, co robi komputer. Według mojej logiki polecenie powinno być

cat file1 file2 2>&1 > file.txt

ale to nie jest poprawne.

iDontKnowBetter
źródło

Odpowiedzi:

46

Łatwiej mi myśleć o korzystaniu z zadań.

  • > jest jak =
  • & jest jak $

Zaczynasz od

1 = /dev/tty
2 = /dev/tty

wtedy twój pierwszy przykład 1> file.txt 2>&1, tak

1 = file.txt
2 = $1           # and currently $1 = file.txt

zostawiając cię z

1 = file.txt
2 = file.txt

Jeśli zrobiłeś to w inny sposób, zacznij od nowa

1 = /dev/tty
2 = /dev/tty

to 2>&1 > file.txtrobi

2 = $1           # and currently $1 = /dev/tty
1 = file.txt

więc końcowy wynik to

1 = file.txt
2 = /dev/tty

a ty tylko przekierowałeś stdout, nie stderr.

Mikel
źródło
w pewnym sensie mam analogię, ale jest to mylące - co oznacza $skrót?
Eliran Malka
W zadaniu typu var=$othervar, $wprowadza nazwę zmiennej po prawej stronie. W przekierowania jak 2>&1, &wprowadza numer deskryptora pliku na prawej stronie. Mówię, że możesz myśleć o tym jak o „plik 2 równa się plik 1”. (Istnieją jednak dwa rodzaje równości: <oznacza „do czytania” i >oznacza „do pisania”.)
Mikel
12

Kolejność przekierowań jest ważna i należy je czytać od lewej do prawej .

Na przykład: command 2>&1 >somefileoznacza:

  1. Przekieruj stderr(mianowicie 2) do bieżącego miejsca docelowego stdout(w tym momencie terminalu).
  2. Następnie zmień, stdoutaby przejść do somefile.

Więc w tym przypadku stderridzie do terminala i stdoutprzechodzi do pliku, który prawdopodobnie nie jest tym, czego prawdopodobnie chcesz.

Z drugiej strony command >somefile 2>&1oznacza:

  1. Przekieruj stdoutdosomefile
  2. Następnie przekieruj stderrdo tego samego miejsca docelowego co stdout( somefile).

W tym ostatnim przypadku zarówno stderri stdoutprzejdź do somefile, co prawdopodobnie jest tym, czego chcesz.

Amelio Vazquez-Reina
źródło
4
cat file1 file2 1> file.txt 2>&1

>& W rzeczywistości oznacza duplikat, używa wywołania systemowego dup do mapowania nowego deskryptora pliku na już otwarty plik.

Więc (bash) najpierw musisz otworzyć nowy stdout, mówiąc „i przekieruj stderr na dowolne ustawione stdout”.

X Tian
źródło
to jest niesamowite! zastanawiałem się nad tym &. czy mógłbyś załączyć kilka odniesień do tej składni, lub - jeszcze lepiej - jakieś dobre zasoby we wspomnianym systemie dup?
Eliran Malka
1
„man dup” dokumentuje wywołanie systemowe.
X Tian
ma sens :) dzięki
Eliran Malka