Różnica między 2> i -, 2> / dev / null, | &, &> / dev / null i> / dev / null 2> i 1

192

Po prostu szukam różnicy między

  • 2>&-
  • 2>/dev/null
  • |&
  • &>/dev/null
  • >/dev/null 2>&1

i ich przenoszenie z non-Bourne shellsniczym tcsh, mkshitp

Det
źródło
2
Zauważ, że chociaż mksh obsługuje &>kompatybilność bash GNU, zdecydowanie zaleca się, aby tego nie używać, ponieważ parsowanie może przerwać semantykę istniejących skryptów POSIX, a mksh wyłącza to już w trybie POSIX.
mirabilos
Widziałem też, ^ /dev/nullco to robi?
balupton

Odpowiedzi:

241

Na tle:

  • numer 1 = średnia z (czyli wyjścia)
  • numer 2 = błąd standardowy (tj STDERR)
  • jeśli liczba nie jest wyraźnie podana, wówczas liczba 1 jest przyjmowana przez powłokę (bash)

Najpierw zajmiemy się ich funkcją. Więcej informacji można znaleźć w przewodniku Advanced Bash-Scripting Guide .

Funkcje

2>&-

Ogólna postać tego jest taka M>&-, gdzie „M” jest numerem deskryptora pliku. Spowoduje to zamknięcie danych wyjściowych dla dowolnego odwołania do deskryptora pliku, tj. „M” .

2>/dev/null

Ogólna postać tego jest taka M>/dev/null, gdzie „M” jest numerem deskryptora pliku. Spowoduje to przekierowanie deskryptora pliku „M” do /dev/null.

2>&1

Ogólna forma tego jest taka M>&N, w której „M” i „N” są numerami deskryptorów plików. Łączy dane wyjściowe deskryptorów plików „M” i „N” w jednym strumieniu.

|&

To tylko skrót 2>&1 |. Został dodany w Bash 4.

&>/dev/null

To tylko skrót >/dev/null 2>&1. Przekierowuje deskryptor pliku 2 (STDERR) i deskryptor 1 (STDOUT) do /dev/null.

>/dev/null

To tylko skrót 1>/dev/null. Przekierowuje deskryptor pliku 1 (STDOUT) do /dev/null.

Przenośność do non-bash, tcsh, mksh itp.

Nie miałem wiele do czynienia z innymi pociskami poza cshi tcsh. Moje doświadczenie z tymi 2 w porównaniu do operatorów przekierowujących bash jest takie, że bash jest pod tym względem lepszy. Zobacz stronę manuala tcsh, aby uzyskać więcej informacji.

Z poleceń, o które pytałeś, żadne nie jest bezpośrednio obsługiwane przez csh / tcsh. Będziesz musiał użyć różnych składni, aby zbudować podobne funkcje.

slm
źródło
Mamy zwycięzcę. Ale czy nie ma różnicy w wydajności lub niektórych z 2>&-vs 2>/dev/null(poza tym, że niektóre „źle” napisane programy nie rozumieją 2>&-poprawnie)?
Det
3
Nie powinno być różnicy w wydajności.
slm
5
&>był bashod samego początku (i łamie kompatybilność z Bourne i POSIX, ponieważ oznacza to coś innego, ale raczej nie zostanie trafiony). >&i |&pochodzą z (t)csh(i to ich jedyny sposób na przekierowanie stderr). Były zshod początku i zostały dodane dopiero niedawno bash. Zobacz także rcdla lepiej zaprojektowanych operatorów.
Stéphane Chazelas
1
Aktualizacja: o problemie z wydajnością, co zostało również potwierdzone tutaj: unix.stackexchange.com/questions/163955/…
Det
1
Cześć @slm, dziękuję za kontakt. Cieszę się, że moje repo się nie zmieniło (+2-2=0). Teraz, w części dotyczącej edycji, nie edytuję dużo, ale w tym przypadku zrobiłbym to, ponieważ wyjaśnia, że ​​dane po operacji będą na N. Przeczytałem, jak odpowiadasz, i jest bardzo w porządku pod każdym względem. Właśnie ta mała dwuznaczność skłoniła mnie do myślenia, dlatego właśnie wydanie. Ale ok, możesz dodać lub odrzucić, jak chcesz. Mam nadzieję, że mógłbym wyjaśnić tę kwestię. Tak trzymaj.
Dr Beco
11

Ma to na celu przekierowanie STDERR i STDOUT:

  • 2>/dev/null

    Przekieruj STDERR do / dev / null (zapobiegaj wyświetlaniu się na konsoli)

  • |&

    Przekieruj STDERR i STDOUT do STDIN polecenia piped (cmd1 | & cmd2)

  • &>/dev/null

    Przekieruj STDERR i STDOUT do / dev / null (nic nie pojawia się na konsoli)

  • >/dev/null

    Przekieruj STDOUT na / dev / null (tylko STDERR pokazuje się na konsoli)

  • 2>&-

    Służy do zamykania deskryptora pliku używanego z przekierowaniem

Są to wszystkie standardowe metody przekierowania dla powłok Bourne'a.

BriGuy
źródło
4
|&i nie&>/dev/null są przenośne.
Chris Down,
4

Uznaj to za uzupełnienie do wybranej odpowiedzi. Możesz wiedzieć, które formularze są POSIX, a które nie.

W grę wchodzą dwa formularze POSIX:

2.7.2 Przekierowanie danych wyjściowych

Dwa ogólne formaty przekierowywania danych wyjściowych to:

[n]> słowo

[n]> | słowo

gdzie opcjonalne n oznacza numer deskryptora pliku. Jeśli numer zostanie pominięty, przekierowanie powinno odnosić się do standardowego wyjścia (deskryptor pliku 1).

Przekierowanie danych wyjściowych w formacie „>” kończy się niepowodzeniem, jeśli ustawiona jest opcja noclobber (patrz opis zestawu -C), a plik nazwany przez rozwinięcie słowa istnieje i jest plikiem zwykłym. W przeciwnym razie przekierowanie za pomocą „>” lub „> |” formaty powodują, że plik, którego nazwa wynika z rozwinięcia słowa, zostanie utworzony i otwarty do wyprowadzenia na wyznaczonym deskryptorze pliku lub standardowy plik wyjściowy, jeśli nie zostanie określony. Jeżeli plik nie istnieje, zostanie utworzony; w przeciwnym razie po otwarciu zostanie obcięty jako pusty plik.

-

2.7.6 Duplikowanie deskryptora pliku wyjściowego

Operator przekierowania:

[n]> i słowo

powiela jeden deskryptor pliku wyjściowego z drugiego lub zamyka jeden. Jeżeli słowo zamienia się na jedną lub więcej cyfr, deskryptor pliku oznaczony przez n lub standardowe wyjście, jeśli n nie jest określone, powinno być kopią deskryptora pliku oznaczoną słowem; jeżeli cyfry w słowie nie reprezentują deskryptora pliku, który jest już otwarty do wydruku, powinien wystąpić błąd przekierowania; zobacz Konsekwencje błędów powłoki. Jeśli słowo zamienia się w „-”, deskryptor pliku n lub standardowe wyjście, jeśli n nie jest określone, jest zamykane. Próby zamknięcia deskryptora pliku, który nie jest otwarty, nie stanowią błędu. Jeśli słowo zmienia się na coś innego, zachowanie jest nieokreślone.

W związku z tym:

Function      POSIX-compat    POSIX 
2>&-          Yes             close 
2>/dev/null   Yes             redir
2>&1          Yes             dup 
|&            No              
&>/dev/null   No
>/dev/null    Yes             redir
>&/dev/null   ?               ?dup

Ostatni wiersz nie znajduje się w pierwotnym pytaniu, ale działa bez zarzutu w bash. (Działa również z / dev / tty podstawiony na / dev / null).

Craig Hicks
źródło
1
Zawsze chcę wiedzieć więcej.
Det