Używanie grep z potokiem i ampersand do filtrowania błędów z find

22

Używam cygwin, aby znaleźć plik na dysku.

Jednak muszę wyłączyć komunikaty o odmowie uprawnień (w przeciwnym razie wyniki zostaną ukryte w komunikatach o błędach). Działa następujące polecenie:

find -name 'myfile.*' |& grep -v "Permission denied"

Nie rozumiem, dlaczego znak ampersand musi być wprowadzony do tego polecenia, spodziewałbym się, że to zadziała, ale nie działa.

find -name 'myfile.*' | grep -v "Permission denied"

Proszę wyjaśnić znaczenie ampersand.

Henrik K.
źródło

Odpowiedzi:

24

W systemach uniksopodobnych istnieją dwie ścieżki wyjściowe, które jeśli pozostaną niezmodyfikowane, wyślą dane wyjściowe na ekran. Standardowy błąd (lub stderr) to taki, który wychwytuje większość awarii i warunków błędów.

Aby przekazać komunikat o odmowie zezwolenia w stderr do tego samego strumienia wyjściowego co „zwykłe wyjście”, należy połączyć oba. W twoim przykładzie, grep -vaby poprawnie na nim operować, łączysz stdout (standardowe wyjście) i stderr z tajemniczą składnią, którą widzisz.

Z podręcznika GNU Bash sekcja 3.2.2 Rurociągi :

If „ |&” jest używany, command1 „S błąd standardowy, oprócz standardowe wyjście jest połączone command2 „s standardowe wejście przez przewód; jest skrótem od 2>&1 |. To niejawne przekierowanie standardowego błędu na standardowe wyjście jest wykonywane po wszelkich przekierowaniach określonych przez polecenie.

Ponadto, jak wskazuje geirha, jeśli chcesz po prostu pozbyć się wydajności stderr, chciałbyś zrobić coś takiego

find -name 'myfile.*' 2> /dev/null

a może

find -name 'myfile.*' 2> /tmp/errorlog

I zauważ, że jeśli masz ciągi poleceń, takie jak findprzekazywanie ich danych wyjściowych xargs, musisz umieścić cały potok poleceń w nawiasach, aby przechwycić dane wyjściowe ze wszystkich składników polecenia. Na przykład,

(find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 )  2> /dev/null

Jeśli pominąłeś nawiasy i zrobiłeś to zamiast tego -

find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 2> /dev/null

nadal widzisz błędy odmowy uprawnień z find lub egrep, ale stderr zostanie przekierowany dla xargs.

Jak widzieliście, prawdopodobnie wyrzucicie stderr dopiero po obejrzeniu jego zawartości podczas uruchomienia testowego.

Należy zauważyć, że z GNU findio ile mogę powiedzieć, każdy POSIX findThe -printopcja jest niejawna. Jeśli chcesz, możesz nadal podać je wyraźnie.

Belacqua
źródło
Wydaje się być tylko bash4 + wiki.bash-hackers.org/bash4#redirection
Luke Exton
1
@LukeExton Tak. W innych powłokach 2>&1 |można użyć zamiast |&(tzn. Można jawnie przekierować stderr na stdout, a następnie przesłać go do następnego polecenia w potoku).
Eliah Kagan
2> >( grep filter )jest również przydatny
user1133275