Jak mogę wykluczyć wszystkie wiadomości „odmowa zgody” z „znaleźć”?

794

Muszę ukryć wszystkie wiadomości, którym odmówiono zgody przed:

find . > files_and_folders

Eksperymentuję, kiedy pojawia się taka wiadomość. Muszę zebrać wszystkie foldery i pliki, do których nie powstają.

Czy można skierować poziomy uprawnień do files_and_folderspliku?

Jak mogę ukryć błędy w tym samym czasie?

Léo Léopold Hertz 준영
źródło

Odpowiedzi:

259

Uwaga:
* Ta odpowiedź prawdopodobnie jest głębsza niż uzasadnia przypadek użycia i find 2>/dev/nullmoż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 findponiż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 bashlubzsh , istnieje rozwiązanie, które jest solidne, a jednocześnie dość proste , wykorzystując tylko findfunkcje zgodne z POSIX ; chociaż bashsam 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 grepdane wyjściowe mogą pojawić się po find zakończeniu, ponieważ ogólne polecenie nie czeka na zakończenie polecenia w środku >(...). W bashmożna temu zapobiec, dołączając | catdo 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 basha zsh, kshwspiera 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 findstderr strumienia komendy użytkownika), które zawierają frazę Permission deniedi wysyła pozostałe linie na stderr ( >&2).

Podejście to:

  • solidny : grepjest 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 : findkod 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>&1musi być na pierwszym miejscu .

Przechwytywanie wyjścia standardowego w pliku z góry umożliwia 2>&1wysyłanie tylko komunikatów o błędach przez potok, który grepnastępnie może jednoznacznie działać.

Jedynym minusem jest to, że ogólny kod wyjścia będzie grepkomenda 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 findkod 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: 1jeśli tak, w 0przeciwnym 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 findkodu 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 3służy do tymczasowego wymiany stdout ( 1) i stderr ( 2) tak, że komunikaty o błędach sam może być wyprowadzony do greppoprzez standardowe wyjście.

Bez tych przekierowań zarówno dane (ścieżki plików), jak i komunikaty o błędach byłyby przesyłane potokowo grepprzez stdout, a grepwó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 deniedbłędy mogą się nadal pojawiać: find ! -readable -prunezgłasza takie błędy w elementach podrzędnych katalogów, do których bieżący użytkownik ma ruprawnienia, ale brakuje xuprawnień (wykonywalnych). Powodem jest to, że ponieważ sam katalog jest czytelny, -prunenie jest wykonywany, a próba zejścia do tego katalogu wywołuje następnie komunikaty o błędach. To powiedziawszy, typowym przypadkiem jest brak rpozwolenia.

    • 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 findpolecenia „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 -namefiltr 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_foldersjak 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_fileryzykuje 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.

mklement0
źródło
4
Krótkie pytanie: dlaczego używasz substytucji procesu, a nie tylko potoku find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2:?
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Jeśli nie chcesz wyprowadzać pliku zewnętrznego, po prostu zrób więcej hydrauliki:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Po prostu jest zgodny z POSIX. Podstawienia procesów >(...)są specyficzne dla Bash.
gniourf_gniourf
2
Nie jestem pewien, czy findnależy zachować i reklamować zachowanie findkodu wyjścia: kod wyjścia jest notorycznie bezużyteczny. Tutaj najprawdopodobniej będzie ona niezerowa (i bezużyteczna).
gniourf_gniourf
3
POSIX wyraźnie wymaga execute/searchuprawnień w trybie plików, aby „przeszukać” katalog (pobrać i-węzły zawartych plików). findrobi to, aby zejść do podkatalogu (oprócz wymagania readpozwolenia na listę plików w katalogu). To nie jest „błąd” ani „błąd przenoszenia”.
wjordan
542

Posługiwać się:

find . 2>/dev/null > files_and_folders

To oczywiście ukrywa nie tylko Permission deniedbłędy, ale wszystkie komunikaty o błędach.

Jeśli naprawdę chcesz zachować inne możliwe błędy, takie jak zbyt wiele przeskoków w dowiązaniu symbolicznym, ale nie te, którym odmówiono zezwolenia, prawdopodobnie będziesz musiał szybko zgadywać, że nie masz wielu plików o nazwie „odmowa uprawnień” i próbuj:

find . 2>&1 | grep -v 'Permission denied' > files_and_folders

Jeśli chcesz filtrować tylko standardowy błąd, możesz użyć bardziej skomplikowanej konstrukcji:

find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2

I / O przekierowania na findpolecenia jest następująca: 2>&1 > files_and_folders |. Potok przekierowuje standardowe wyjście do greppolecenia i jest stosowane najpierw. 2>&1Wysyła standardowy błąd w tym samym miejscu co standardowe wyjście (rury). > files_and_foldersWysyła standardowe wyjście (ale nie błąd standardowy) do pliku. W efekcie komunikaty zapisywane z błędem standardowym są przesyłane w dół potoku, a zwykłe wyjście findjest zapisywane w pliku. grepFiltry standardowe wyjście (można zdecydować jak selektywne chcesz go mieć, a może trzeba zmienić pisownię w zależności od kraju i O / S) i ostateczna>&2oznacza, że ​​pozostałe komunikaty o błędach (zapisane na standardowe wyjście) ponownie przechodzą w standardowy błąd. Ostateczne przekierowanie można uznać za opcjonalne na terminalu, ale bardzo dobrym pomysłem byłoby użycie go w skrypcie, aby komunikaty o błędach pojawiały się przy standardowym błędzie.

Istnieje nieskończona liczba odmian tego tematu, w zależności od tego, co chcesz zrobić. Działa to na każdym wariancie Uniksa z dowolną pochodną powłoki Bourne'a (Bash, Korn,…) i dowolną wersją zgodną z POSIX find.

Jeśli chcesz dostosować się do konkretnej wersji findposiadanej w systemie, mogą być dostępne alternatywne opcje. findW szczególności GNU ma niezliczone opcje niedostępne w innych wersjach - zobacz aktualnie akceptowaną odpowiedź na jeden taki zestaw opcji.

Jonathan Leffler
źródło
9
Jeśli jesteś podobny do mnie, zauważ, że brak miejsca jest ważny! 2>/dev/null, bez miejsca!
Nik
20
2>To jedno urządzenie bez jakichkolwiek przerw; możesz mieć spację między nim a nazwą pliku. Podobnie z innymi przekierowaniami, takimi jak 2>&1(który przekierowuje standardowy błąd w to samo miejsce, w którym idzie standardowe wyjście), lub 2>&-który zamyka standardowy błąd itp. Zobacz pozostałe przekierowania, aby uzyskać szczegółowe informacje. (Powyższy kod jest ogólną powłoką podobną do POSIX, a nie specyficzną dla bash.)
Jonathan Leffler,
3
Musiałem użyć dużej litery P, ponieważ to właśnie wyświetli mój terminal: znajdź. 2> i 1 | grep -v „Odmowa zezwolenia”
David Doria
4
Jak to jest dopuszczalne rozwiązanie? 1) Przekierowujesz WSZYSTKIE błędy do dev / null 2) Filtrujesz jawny ciąg błędów !! W zależności od tego jest on znany jako kruchy, a co, jeśli Twój plik znajdował się w katalogu o nazwie „odmowa dostępu”? Ups!
Gunchars,
10
Sprzeciwiam się ciągom błędów greppingu, aby zmodyfikować dane wyjściowe programu. Będzie to działało przez większość czasu, ale proste nie jest poprawnym rozwiązaniem (znajdź poniżej perms jest). Podając przykład, nie będzie to działać w systemie OSX, ponieważ błąd brzmi „Odmowa zezwolenia”. To samo dla każdego innego systemu, w którym występują nawet niewielkie różnice w ciągu błędu (ktoś internacjonalizacji?)
Gunchars,
285

Posługiwać się:

find . ! -readable -prune -o -print

lub bardziej ogólnie

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • aby uniknąć „Odmowy zezwolenia”
  • I NIE pomijaj (innych) komunikatów o błędach
  • ORAZ uzyskaj status wyjścia 0 („wszystkie pliki zostały przetworzone pomyślnie”)

Współpracuje z: find (GNU findutils) 4.4.2. Tło:

  • -readableTest mecze plików czytelny. !Operator zwraca true, gdy test jest fałszywe. I ! -readabledopasowuje nieczytelne katalogi (i pliki).
  • -pruneDziałanie nie zejść do katalogu.
  • ! -readable -prune można przetłumaczyć na: jeśli katalog nie jest czytelny, nie schodź do niego.
  • -readableBadanie uwzględnia list kontroli dostępu i innych artefaktów uprawnieniami którym -permignoruje testowe.

Zobacz także find(1) stronę, aby uzyskać więcej informacji.

Michael Brux
źródło
6
różnice są już wspomniane. jeśli nie rozumiesz, to odpowiedzi mogą nie mieć dla ciebie znaczenia? STDOUT jest taki sam - STDERR jest inny (otrzymujesz inne komunikaty o błędach z tą odpowiedzią) - $? jest inny (czy 0 jest „udane” przy tej odpowiedzi, gdy nie występuje żaden inny błąd - zawsze> 0 „nie udaje się” przy przekierowywaniu do dev / null) - może ktoś potrzebuje „poprawnej” $? według scenariusza
Michael Brux,
6
@Masi najbardziej oczywistą wadą jest odpowiedź Jonathana (grep -v) wyklucza nazwę pliku, która zawiera „Odmowa zezwolenia” :)
Owoce
65
Uważam za stosowne dodać tutaj, że jeśli chcesz dodać inne kryteria wyszukiwania, należy to zrobić za pomocą -o:find . ! -readable -prune -o -name '*.txt'
tempestadept
22
Zauważ, że POSIX findnie obejmuje -readablejako opcji; nie dotyczy to również findBSD, a tym samym Mac OS X (nie jestem pewien co do innych systemów). Tak więc, jeśli masz findgwarancję GNU , działa to świetnie, ale nie jest oczywiste, jak to dostosować, jeśli nie możesz zagwarantować, że system ma findzainstalowany GNU . (Będzie działał dobrze w systemie Linux; może, ale nie musi działać gdzie indziej.)
Jonathan Leffler
6
find . ! -readable -prune -o -name '*.txt'wydaje się, że nie działa na Ubuntu 14.04 przy użyciu find 4.2.2. Wygląda na to, że wchłania -name. Z jakiegoś dziwnego powodu odnoszę sukcesfind . \( ! -readable -prune \) -o -name '*.txt' -print
con-f-use
110

Jeśli chcesz rozpocząć wyszukiwanie od roota „/”, prawdopodobnie zobaczysz coś takiego jak:

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

To z powodu pozwolenia. Aby rozwiązać ten problem:

  1. Możesz użyć polecenia sudo:

    sudo find /. -name 'toBeSearched.file'

Pyta o hasło superużytkownika, po wpisaniu hasła zobaczysz wynik, który naprawdę chcesz. Jeśli nie masz uprawnień do korzystania z polecenia sudo, co oznacza, że ​​nie masz hasła superużytkownika, najpierw poproś administratora systemu o dodanie Cię do pliku sudoers.

  1. Możesz użyć przekierowania Standardowego wyjścia błędu z (Generalnie wyświetlanie / ekran) do jakiegoś pliku i unikać wyświetlania komunikatów o błędach na ekranie! przekieruj do specjalnego pliku / dev / null:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. Możesz użyć przekierowania Standardowego wyjścia błędu z (Generalnie wyświetlanie / ekran) na Standardowe wyjście (Generalnie wyświetlanie / ekran), a następnie potokować za pomocą polecenia grep z parametrem -v „invert”, aby nie wyświetlać linii wyjściowych, dla których „Odmowa dostępu” pary słów:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
Fatih Aksu
źródło
7
@ scottmrogowski poza tym, że nie odpowiada na pytanie ... 1. Poproś administratora systemu o dodanie cię do pliku sudoers. 2.sudo find...
Stephen
1
dokładnie to, czego szukałem!
DankMasterDan
92

Musiałem użyć:

find / -name expect 2>/dev/null

określając nazwę tego, co chciałem znaleźć, a następnie każąc przekierować wszystkie błędy na / dev / null

spodziewaj się, że jest to lokalizacja oczekiwanego programu, którego szukałem.

Jeremy
źródło
3
@Masi, polecenie w odpowiedzi nie jest używane expect. Zamiast tego expectjest po prostu nazwą pliku, który to polecenie spróbuje znaleźć.
Dhruv Kapoor
2
Ślepe przekierowanie wszystkich danych wyjściowych stderr tylko w celu zignorowania jednej klasy komunikatów o błędach jest ogólnie złym pomysłem - stracisz wszystkie inne arbitralne błędy w procesie.
Josip Rodin
59

Rura stderrdo /dev/nullstosując 2> / dev / null

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

Matt
źródło
2
Działa to dobrze dla mnie nawet w systemie Mac OSX. Lub nawetfind . -name '...' -print 2>/dev/null
shadowsheep
30

Możesz także użyć predykatów -permi, -pruneaby uniknąć zejścia do nieczytelnych katalogów (zobacz też Jak usunąć instrukcje wydruku „odmowa uprawnień” z programu znajdującego? - Unix i Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
sdaau
źródło
4
-perm -g+r,u+r,o+rpo prostu dopasowuje pliki, które mają uprawnienia r(do odczytu) ustawione dla wszystkich 3 podmiotów zabezpieczeń pliku , co nie ma bezpośredniego związku z tym, czy bieżący użytkownik może odczytać ten plik, czy nie. Może zarówno pomijać pliki, które bieżący użytkownik może odczytać, jak i dopasowywać pliki, których nie mogą.
mklement0
Myślę, że find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printbyłoby dobrym rozwiązaniem.
Mattia72
2
@ Mattia72: Nie, to jest zasadniczo niemożliwe, aby w pełni naśladować -readablez -perm- patrz mój poprzedni komentarz i Rozważmy następujący przykład: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rwydruki file, ponieważ jego użytkownik odczytać bit jest ustawiony, ale dotyczy on The nobodyużytkownika, a nie bieżącego użytkownika. Bieżący użytkownik nie może odczytać tego pliku; spróbuj cat file. Zobacz także: moja odpowiedź .
mklement0
23

Przekieruj błąd standardowy. Na przykład, jeśli używasz bash na maszynie uniksowej, możesz przekierować standardowy błąd do / dev / null w następujący sposób:

find . 2>/dev/null >files_and_folders
Jason Coco
źródło
20

Chociaż powyższe podejścia nie uwzględniają przypadku systemu Mac OS X, ponieważ Mac OS X nie obsługuje -readableprzełącznika, w ten sposób można uniknąć błędów „odmowy zezwolenia” w danych wyjściowych. To może komuś pomóc.

find / -type f -name "your_pattern" 2>/dev/null.

Jeśli używasz innego polecenia find, na przykład, aby znaleźć rozmiar plików określonego wzorca w katalogu 2>/dev/null, nadal działałby, jak pokazano poniżej.

find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$.

Zwróci to całkowity rozmiar plików o danym wzorze. Uwaga 2>/dev/nullna końcu polecenia find.

Bunti
źródło
Ładne wiązanie do OS X! Odpowiedź Jonathana wyjaśnia tę część 2>/dev/null. Czy możesz wyjaśnić tę część -exec du -ch {} + 2>/dev/null | grep total$.
Léo Léopold Hertz
1
@Masi Możesz użyć dowolnego polecenia z -execopcją, aby podjąć dalsze działania na plikach lub katalogach znalezionych przez findpolecenie. du -ch file_patternoblicza rozmiar każdego dopasowanego pliku, file_patterna ostatni wiersz tego wyniku jest sumą wszystkich plików, które pasowały file_pattern. Zobacz stronę podręcznika dla du. grep totalpo prostu filtruje linię, która wyodrębnia sumę całkowitą (która jest ostatnią linią).
Bunti
13

Błędy te są drukowane na standardowe wyjście błędów (fd 2). Aby je odfiltrować, po prostu przekieruj wszystkie błędy do / dev / null:

find . 2>/dev/null > some_file

lub najpierw połącz stderr i stdout, a następnie wytłumacz te konkretne błędy:

find . 2>&1 | grep -v 'Permission denied' > some_file
viraptor
źródło
11

Prosta odpowiedź:

find . > files_and_folders 2>&-

2>&-zamyka ( -) standardowy deskryptor pliku błędów ( 2), więc wszystkie komunikaty o błędach są wyciszane.

  • Kod zakończenia będzie nadal wyświetlany, 1jeśli w Permission deniedprzeciwnym razie zostaną wydrukowane jakiekolwiek błędy

Solidna odpowiedź dla GNU find:

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

Przekazać dodatkowe opcje find, które -prune(zapobieganie schodząc do), ale wciąż -printdowolnego katalogu ( ), która nie ( ) mają zarówno i uprawnienia, lub ( ) każdy inny plik.-typed\!-readable-executable-o-print

  • -readablea -executableopcje to rozszerzenia GNU, nie będące częścią standardu POSIX
  • Może nadal zwracać ' Permission denied' w przypadku nieprawidłowych / uszkodzonych plików (np. Zobacz raport o błędach wpływający na systemy plików zamontowane w kontenerze przy użyciu lxcfs<v2.0.5)

Solidna odpowiedź, która działa z każdym kompatybilnym z POSIX find(GNU, OSX / BSD itp.)

{ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1

Użyj potoku, aby przekazać standardowy strumień błędów grep, usuwając wszystkie wiersze zawierające 'Permission denied'ciąg.

LC_ALL=Custawia locale POSIX stosując zmienną środowiska , 3>&2 2>&1 1>&3a 3>&2 2>&1 powielone deskryptory plików do rury strumień standardowego błędu grepi [ $? = 1 ]zastosowania []odwrócić przez zwrócony kod błędu grepdo w przybliżeniu pierwotnej zachowanie find.

  • Filtruje również wszelkie 'Permission denied'błędy wynikające z przekierowania wyjścia (np. Jeśli files_and_folderssam plik nie jest zapisywalny)
Wjordan
źródło
Co sądzisz o propozycji odpowiedzi JordiFerran? - - Czy potrafisz porównać swoją odpowiedź?
Léo Léopold Hertz -
2
Skrypt powłoki tej odpowiedzi, jak wspomniano, nie ma ogólnego zastosowania (wyświetla tylko katalogi pasujące do $ {m_nazwa_finda}) i zawiera kilka opcji niezwiązanych z pytaniem (nice, / home *, -maxdepth 5, -follow). Ta odpowiedź rozwiązuje konkretniej kwestię „filtrowania katalogów czytelnych, ale niewykonywalnych” bardziej zwięźle, przy jednoczesnym zachowaniu ogólnego przeznaczenia.
wjordan
1
@wjordan: Dzięki. Usunąłem swoje komentarze, ale nadal obowiązuje jedna kwestia: -permrozwiązanie oparte na wartości nie jest warte przedstawienia, ponieważ bardziej fundamentalnie niż sugeruje to cytat, robi coś innego niż zamierzone: jest to test skoncentrowany wyłącznie na plikach , odnoszący się do właściciela pliku i grupa, z których żadna nie ma żadnych gwarantowanych relacji z użytkownikiem wywołującym polecenie (zobacz moją odpowiedź . Wygląda na to, że twoje poprawione rozwiązanie GNU nie łapie teraz błędów odmowy
dostępu
Nie rozpoznaję składni, której używasz (ani jako GNU, ani jako BSD), ale pozwól mi zilustrować mój punkt widzenia samodzielnym przykładem: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rwypisuje file, ponieważ jego bit odczytu użytkownika jest ustawiony, ale odnosi się do nobodyużytkownika , nie bieżący użytkownik. Bieżący użytkownik nie może odczytać tego pliku; spróbuj cat file.
mklement0
1
@ mklement0 dzięki za dyskusję, udało mi się stworzyć zachowanie, które opisałeś w innym teście (nie wiem, co zrobiłem źle za pierwszym razem), wygląda na to, że -permnie działa na określenie aktualnych uprawnień użytkownika. Usunąłem tę alternatywę z tej odpowiedzi.
wjordan
4

Aby uniknąć tylko za pozwoleniem zaprzeczył ostrzeżenia, powiedz znaleźć ignorować nieczytelne pliki przez przycinanie ich wyszukiwania. Dodaj wyrażenie jako OR do swojego znaleziska, takie jak

find / \! -readable -prune -o -name '*.jbd' -ls

Mówi się głównie o (dopasuj nieczytelny plik i przyciąć go z listy) LUB (dopasuj nazwę jak * .jbd i wyświetl ją [za pomocą ls]) . (Pamiętaj, że domyślnie wyrażenia są AND połączone razem, chyba że użyjesz -lub.) Potrzebujesz -ls w drugim wyrażeniu, bo w przeciwnym razie find może dodać domyślną akcję, aby pokazać jedno z pasujących elementów, które pokaże również wszystkie nieczytelne pliki .

Ale jeśli szukasz prawdziwych plików w swoim systemie, zwykle nie ma powodu, aby szukać w / dev, który ma wiele wielu plików, więc powinieneś dodać wyrażenie wykluczające ten katalog, takie jak:

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

Więc (dopasuj nieczytelny plik i przycinaj z listy) LUB (dopasuj ścieżkę / dev i przycinaj z listy) LUB (dopasuj plik jak * .jbd i wyświetl go) .

simpleuser
źródło
4

posługiwać się

sudo find / -name file.txt

Jest głupi (ponieważ podnosisz wyniki wyszukiwania) i nie jest bezpieczny, ale jest o wiele krótszy do napisania.

zamglenie
źródło
Przeszukujesz tutaj cały system plików, więc rozumiesz przez to „podniesienie wyszukiwania”. Dlaczego nazywasz to niezabezpieczonym? Ponieważ szuka całego systemu plików?
Léo Léopold Hertz -
2
Ponieważ sudo uruchamia polecenie find z uprawnieniami administratora, co w zasadzie jest złym pomysłem. Zasady segregacji i najmniejszych uprawnień są naruszane.
mgła
3
„Wzniesienie” tutaj jest przywilejem, do rootowania, z sudo. Ryzykujesz, że cały system zostanie pomieszany przez błąd w findlub złośliwą wersję, lub nieprawidłowe wywołanie, które zapisuje coś nieoczekiwanie, co nie mogłoby się zdarzyć, gdybyś uruchomił to z normalnymi uprawnieniami.
tripleee
2

Żadna z powyższych odpowiedzi nie działała dla mnie. Cokolwiek znajduję w Internecie, koncentruje się na: ukrywaniu błędów. Brak poprawnie obsługuje kod powrotu / kod zakończenia procesu. Używam poleceń find w skryptach bash, aby zlokalizować niektóre katalogi, a następnie sprawdzić ich zawartość. Oceniam powodzenie komendy za pomocą kodu wyjścia: wartość zero działa, w przeciwnym razie kończy się niepowodzeniem.

Odpowiedź podane powyżej przez Michaela Brux działa czasami. Ale mam jeden scenariusz, w którym się nie udaje! Odkryłem problem i sam go naprawiłem. Muszę przycinać pliki, gdy:

it is a directory AND has no read access AND/OR has no execute access

Zobacz kluczową kwestię tutaj: ORAZ / LUB. Jedna dobra sugerowana sekwencja warunków, którą przeczytałem, to:

-type d ! -readable ! -executable -prune

To nie zawsze działa. Oznacza to, że suszona śliwka jest uruchamiana, gdy mecz jest:

it is directory AND no read access AND no execute access

Ta sekwencja wyrażeń kończy się niepowodzeniem, gdy przyznany jest dostęp do odczytu, ale nie ma dostępu do wykonania.

Po kilku testach zdałem sobie z tego sprawę i zmieniłem rozwiązanie skryptu powłoki na:

nice find / home * / -maxdepth 5 -follow \
    \ (-type d -a ! \ (-readable -a -executable \) \) -prune \
    -o \
    \ (-type d -a -readable -a - wykonywalny -a -name "$ {m_nazwa_pliku}" \) -print

Kluczem tutaj jest umieszczenie „nieprawdziwego” wyrażenia łączonego:

has read access AND has execute access

W przeciwnym razie nie ma pełnego dostępu, co oznacza: przycinanie. Okazało się to dla mnie skuteczne w jednym scenariuszu, w którym poprzednie sugerowane rozwiązania zawiodły.

Poniżej zamieszczam szczegółowe informacje techniczne dotyczące pytań w sekcji komentarzy. Przepraszam, jeśli szczegóły są nadmierne.

  • Dlaczego warto używać polecenia nice? Mam tutaj pomysł . Początkowo myślałem, że byłoby miło zmniejszyć priorytet procesu, patrząc na cały system plików. Uświadomiłem sobie, że nie ma to dla mnie sensu, ponieważ mój skrypt jest ograniczony do kilku katalogów. Zmniejszyłem -maxdepth do 3.
  • Dlaczego warto szukać w / home * /? To nie dotyczy tego wątku. Wszystkie aplikacje instaluję ręcznie za pomocą kompilacji kodu źródłowego z użytkownikami nieuprzywilejowanymi (nie root). Są instalowane w „/ home”. Mogę mieć wiele plików binarnych i wersji mieszkających razem. Muszę zlokalizować wszystkie katalogi, sprawdzić i wykonać kopię zapasową w sposób master-slave. Mogę mieć więcej niż jeden „/ home” (kilka dysków działających na dedykowanym serwerze).
  • Dlaczego warto korzystać z opcji -follow? Użytkownicy mogą tworzyć dowiązania symboliczne do katalogów. Jego użyteczność zależy, muszę prowadzić rejestr absolutnych ścieżek.
Jordi Ferran
źródło
Dziękuję za odpowiedź i miłe spostrzeżenia! Otworzyłem nagrodę tutaj, aby lepiej wyświetlić podgląd odpowiedzi. Myślę, że to miłe odkrycie nie uniemożliwia dostępu do odczytu i wykonywania. - - Czy możesz wyjaśnić, dlaczego używasz nicei find $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz -
2
Skrypt powłoki jak stwierdził nie jest ogólnego przeznaczenia (tylko wymienia katalogi dopasowywania ${m_find_name}) i zawiera kilka opcji, które nie mają na pytanie ( nice, /home*, -maxdepth 5, -follow). Dodałem odpowiedź, która rozwiązuje bardziej konkretnie kwestię „filtrowania katalogów czytelnych, ale niewykonywalnych” bardziej zwięźle, przy jednoczesnym zachowaniu ogólnego przeznaczenia.
wjordan
2

Możesz użyć grep -v invert-match

-v, --invert-match        select non-matching lines

lubię to:

find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders

Powinien do magii

Leonardo Hermoso
źródło
2

- = Dla MacOS = -

Stwórz nowe polecenie używając aliasu: po prostu dodaj w linii ~ / .bash_profile:

alias search='find / -name $file 2>/dev/null'

aw nowym oknie terminalu możesz to nazwać:

$ file=<filename or mask>; search

na przykład:

$ plik = etc; Szukaj

Jan aka uptech
źródło
1

Jeśli używasz CSH lub TCSH, oto rozwiązanie:

( find . > files_and_folders ) >& /dev/null

Jeśli chcesz wyprowadzać dane do terminala:

( find . > /dev/tty ) >& /dev/null

Jednak, jak opisuje FAQ „csh-whynot”, nie powinieneś używać CSH.

Kayle Sawyer
źródło
Chcę grepować wszystkie pliki txt i wykluczyć ukryte pliki / katalog, pomijać komunikat „Odmowa zezwolenia” do wydrukowania. Używam powłoki csh. Użyłem poniższych poleceń i one nie działają find. -type f -iname " .txt" -not -path '* / \. „| egrep -v „Odmowa zezwolenia” znajdź. -type f -iname " .txt" -not -path '* / \. '2> / dev / null Błąd poniżej. find: ścieżki muszą poprzedzać wyrażenie: 2 Zastosowanie: find [-H] [-L] [-P] [-Olevel] [-D pomoc | drzewo | wyszukiwanie | stat | stawki | opt | exec] [ścieżka ...] [wyrażenie]
yadav