Uwaga:
* Ta odpowiedź prawdopodobnie jest głębsza niż uzasadnia przypadek użycia i find 2>/dev/null
może być wystarczająca w wielu sytuacjach. Może to nadal być interesujące z perspektywy wieloplatformowej i do dyskusji nad niektórymi zaawansowanymi technikami powłoki w celu znalezienia rozwiązania, które jest tak solidne, jak to możliwe, nawet jeśli chronione przypadki mogą być w dużej mierze hipotetyczne.
* Jeśli Twój system jest skonfigurowany do wyświetlania zlokalizowanych komunikatów o błędach , poprzedzaj find
poniższe wywołania znakiem LC_ALL=C
( LC_ALL=C find ...
), aby mieć pewność, że komunikaty w języku angielskim będą zgłaszane, aby grep -v 'Permission denied'
działało zgodnie z przeznaczeniem. Niezmiennie jednak żadnych komunikatów o błędach, które należy uzyskać wyświetlane będzie wówczas także w języku angielskim.
Jeśli twoja powłoka jest bash
lubzsh
, istnieje rozwiązanie, które jest solidne, a jednocześnie dość proste , wykorzystując tylko find
funkcje zgodne z POSIX ; chociaż bash
sam nie jest częścią POSIX, większość współczesnych platform Unixowych jest z nim wyposażona, dzięki czemu to rozwiązanie jest przenośne:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Uwaga: Istnieje niewielka szansa, że niektóre grep
dane wyjściowe mogą pojawić się po find
zakończeniu, ponieważ ogólne polecenie nie czeka na zakończenie polecenia w środku >(...)
. W bash
można temu zapobiec, dołączając | cat
do polecenia.
>(...)
jest (rzadko stosowane) wyjście podstawienie proces , który umożliwia przekierowanie wyjścia (w tym przypadku, stderr wyjście ( 2>
) z stdin wewnątrz polecenia >(...)
.
Oprócz bash
a zsh
, ksh
wspiera ich, jak również co do zasady , ale stara się połączyć je z przekierowaniem z stderr , jak to zrobiono tutaj ( 2> >(...)
), wydaje się być dyskretnie ignorowane (in ksh 93u+
).
grep -v 'Permission denied'
filtruje się ( -v
) wszystkie linie (od find
stderr strumienia komendy użytkownika), które zawierają frazę Permission denied
i wysyła pozostałe linie na stderr ( >&2
).
Podejście to:
solidny : grep
jest stosowany tylko do komunikatów o błędach (a nie do kombinacji ścieżek plików i komunikatów o błędach, potencjalnie prowadzących do fałszywych alarmów), a komunikaty o błędach inne niż te, którym odmówiono zgody, są przekazywane do stderr.
bez skutków ubocznych : find
kod wyjścia jest zachowany: niemożność uzyskania dostępu do co najmniej jednego z napotkanych elementów systemu plików skutkuje kodem wyjścia 1
(chociaż nie powie to, czy wystąpiły również błędy inne niż odmowa uprawnień).
Rozwiązania zgodne z POSIX:
Rozwiązania w pełni zgodne z POSIX mają ograniczenia lub wymagają dodatkowej pracy.
Jeśli find
„s wyjściowy ma być ujęte w pliku, w każdym razie (albo całkowicie stłumiony), a następnie roztwór rurociągu z podstawki odpowiedzi Jonathan Lefflera jest prosta, solidna i POSIX:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Pamiętaj, że kolejność przekierowań ma znaczenie: 2>&1
musi być na pierwszym miejscu .
Przechwytywanie wyjścia standardowego w pliku z góry umożliwia 2>&1
wysyłanie tylko komunikatów o błędach przez potok, który grep
następnie może jednoznacznie działać.
Jedynym minusem jest to, że ogólny kod wyjścia będzie grep
komenda jest , a nie find
„s, co w tym przypadku oznacza: jeśli istnieją żadne błędy w ogóle lub jedynie błędów braku-zaprzeczyć, kod wyjścia będzie 1
(sygnalizacja awarii ), w przeciwnym razie ( błędy inne niż odmowa zgody) 0
- co jest przeciwieństwem zamiaru.
Mimo to find
kod wyjścia jest rzadko używany , ponieważ często przekazuje niewiele informacji poza podstawową awarią, taką jak przejście nieistniejącej ścieżki.
Jednak szczególny przypadek nawet tylko niektórychścieżek wejściowych jest niedostępne z powodu braku uprawnień jest odzwierciedlone w find
„s kod wyjścia (zarówno GNU oraz BSD find
): jeśli wystąpi błąd uprawnienia-odmówiono na każdy z plików przetworzonych, kod wyjścia jest ustawiony 1
.
Następująca odmiana dotyczy:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Teraz kod wyjścia wskazuje, czy wystąpiły błędy inne niż Permission denied
wystąpiły: 1
jeśli tak, w 0
przeciwnym razie.
Innymi słowy: kod wyjścia odzwierciedla teraz prawdziwy cel polecenia: sukces ( 0
) jest zgłaszany, jeśli nie wystąpiły żadne błędy lub wystąpiły tylko błędy odmowy uprawnień.
Jest to prawdopodobnie nawet lepsze niż przekazywanie find
kodu wyjścia, jak w rozwiązaniu u góry.
gniourf_gniourf w komentarzach proponuje (nadal zgodne z POSIX) uogólnienie tego rozwiązania przy użyciu wyrafinowanych przekierowań , które działa nawet przy domyślnym zachowaniu drukowania ścieżek plików na standardowe wyjście :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
W skrócie: deskryptor klienta 3
służy do tymczasowego wymiany stdout ( 1
) i stderr ( 2
) tak, że komunikaty o błędach sam może być wyprowadzony do grep
poprzez standardowe wyjście.
Bez tych przekierowań zarówno dane (ścieżki plików), jak i komunikaty o błędach byłyby przesyłane potokowo grep
przez stdout, a grep
wówczas nie byłyby w stanie odróżnić komunikatu o błędzie Permission denied
od pliku (hipotetycznego) , którego nazwa zawiera zdarzenie Permission denied
.
Tak jak w pierwszym rozwiązaniu, kod wyjścia zgłoszony będzie jednak grep
„nie find
”, ale można zastosować tę samą poprawkę, co powyżej.
Uwagi na temat istniejących odpowiedzi:
Istnieje kilka punktów, aby pamiętać o odpowiedź Michaela Brüx za , find . ! -readable -prune -o -print
:
Wymaga GNU find
; w szczególności nie będzie działać na macOS. Oczywiście, jeśli potrzebujesz tylko polecenia do pracy z GNU find
, nie będzie to dla ciebie problemem.
Niektóre Permission denied
błędy mogą się nadal pojawiać: find ! -readable -prune
zgłasza takie błędy w elementach podrzędnych katalogów, do których bieżący użytkownik ma r
uprawnienia, ale brakuje x
uprawnień (wykonywalnych). Powodem jest to, że ponieważ sam katalog jest czytelny, -prune
nie jest wykonywany, a próba zejścia do tego katalogu wywołuje następnie komunikaty o błędach. To powiedziawszy, typowym przypadkiem jest brak r
pozwolenia.
Uwaga: Poniższy punkt jest kwestią filozofii i / lub konkretnego przypadku użycia i możesz zdecydować, że nie jest on dla ciebie odpowiedni i że polecenie dobrze pasuje do twoich potrzeb, szczególnie jeśli wystarczy wydrukować ścieżki:
- Jeśli konceptualizujesz filtrowanie komunikatów o błędach odmowy uprawnień jako osobne zadanie, które chcesz zastosować do dowolnego
find
polecenia, wówczas odwrotne podejście do proaktywnego zapobiegania błędom odmowy uprawnień wymaga wprowadzenia do find
polecenia „szumu” , co również wprowadza złożoność i logiczne pułapki .
- Na przykład najbardziej pozytywnie oceniany komentarz do odpowiedzi Michaela (w chwili pisania tego tekstu) próbuje pokazać, jak rozszerzyć polecenie, włączając
-name
filtr w następujący sposób:
find . ! -readable -prune -o -name '*.txt'
To jednak nie działa zgodnie z przeznaczeniem, ponieważ wymagane-print
jest działanie końcowe (wyjaśnienie można znaleźć w tej odpowiedzi ). Takie subtelności mogą wprowadzać błędy.
Pierwsze rozwiązanie w odpowiedzi Jonathan Leffler jest , find . 2>/dev/null > files_and_folders
jak sam twierdzi, ślepo wycisza wszystkie komunikaty o błędach (a obejście jest uciążliwe i nie w pełni niezawodne, jak wyjaśnia również). Pragmatycznie rzecz biorąc , jest to jednak najprostsze rozwiązanie , ponieważ możesz z zadowoleniem założyć, że wszelkie błędy będą związane z uprawnieniami.
Odpowiedź zMist , sudo find . > files_and_folders
, jest zwięzły i pragmatyczne, ale źle poinformowani o niczym innym niż tylko drukowanie nazw , ze względów bezpieczeństwa: ponieważ używasz jako głównego użytkownika „, istnieje ryzyko konieczności całego systemu są pomieszane w wyniku błędu w znalezisku lub złośliwą wersję lub niepoprawne wywołanie, które pisze coś nieoczekiwanie, co nie mogłoby się zdarzyć, gdybyś uruchomił to z normalnymi uprawnieniami ”(na podstawie komentarza do odpowiedzi mgły przez trójkę ).
2. rozwiązanie w odpowiedzi viraptor za , find . 2>&1 | grep -v 'Permission denied' > some_file
ryzykuje fałszywych alarmów (ze względu na wysyłanie mieszankę stdout i stderr rurociągiem) oraz, potencjalnie, zamiast zgłaszać niż błędy -permission-odrzucona przez stderr, przechwytuje je obok torów wyjściowych w pliku wyjściowym.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
:?