943 Stimmen

Wie kann ich alle "Zugriff verweigert" Nachrichten von "find" ausschließen?

Ich muss alle Zugriff verweigert Nachrichten ausblenden von:

find . > files_and_folders

Ich experimentiere, wenn solche Nachrichten auftreten. Ich muss alle Ordner und Dateien sammeln, bei denen es nicht auftritt.

Ist es möglich, die Berechtigungsebenen auf die files_and_folders Datei umzuleiten?

Wie kann ich gleichzeitig die Fehler ausblenden?

0 Stimmen

Tolle Frage! Leider funktionieren die ersten drei Antworten einfach nicht unter Debian Linux. Oder zumindest meine Konfiguration davon. Ich brauchte Fatih's Lösung, find /. -name 'toBeSearched.file' 2>/dev/null.

0 Stimmen

Ich fand es am besten, den /proc-Pfad mithilfe der -path-Option auszuschließen. Es hilft, die -prune-Option zu verneinen, um das Drucken von ausgeblendeten Elementen zu vermeiden.

645voto

Jonathan Leffler Punkte 694013

Verwendung:

find . 2>/dev/null > files_and_folders

Dies verbirgt natürlich nicht nur die Fehlermeldungen Berechtigung verweigert, sondern alle Fehlermeldungen.

Wenn Sie wirklich andere mögliche Fehler beibehalten möchten, wie z.B. zu viele Sprünge auf einem Symlink, aber nicht die mit Berechtigung verweigerten, dann müssten Sie wahrscheinlich raten, dass Sie nicht viele Dateien namens 'permission denied' haben und versuchen:

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

Wenn Sie streng nur Standardfehler filtern möchten, können Sie die elaboriertere Konstruktion verwenden:

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

Die I/O-Umleitung im find-Befehl lautet: 2>&1 > files_and_folders |. Das Pipe leitet die Standardausgabe zum grep-Befehl um und wird zuerst angewendet. Das 2>&1 sendet Standardfehler an denselben Ort wie die Standardausgabe (das Pipe). Das > files_and_folders sendet die Standardausgabe (aber nicht den Standardfehler) an eine Datei. Das Endergebnis besteht darin, dass Nachrichten, die an den Standardfehler geschrieben werden, durch das Pipe gesendet werden und die normale Ausgabe von find in die Datei geschrieben wird. Das grep filtert die Standardausgabe (Sie können entscheiden, wie selektiv Sie sein möchten, und die Schreibweise je nach Lokalisierung und Betriebssystem ändern müssen) und das endgültige >&2 bedeutet, dass die erhaltenen Fehlermeldungen (an die Standardausgabe geschrieben) erneut an den Standardfehler gesendet werden. Die letzte Umleitung könnte am Terminal als optional angesehen werden, es wäre jedoch eine sehr gute Idee, sie in einem Skript zu verwenden, damit Fehlermeldungen auf dem Standardfehler erscheinen.

Es gibt unendlich viele Variationen dieses Themas, je nachdem, was Sie tun möchten. Dies funktioniert auf jeder Variante von Unix mit jeder Bourne-Shell-Abspaltung (Bash, Korn, ...) und jeder konformen Version von find.

Wenn Sie sich an die spezifische Version von find anpassen möchten, die auf Ihrem System installiert ist, stehen möglicherweise alternative Optionen zur Verfügung. Insbesondere GNU find hat eine Vielzahl von Optionen, die in anderen Versionen nicht verfügbar sind – siehe die derzeit akzeptierte Antwort für einen solchen Satz von Optionen.

11 Stimmen

Wenn Sie wie ich sind, bemerken Sie, dass der Mangel an Platz wichtig ist! 2>/dev/null, ohne Leerzeichen!

25 Stimmen

Der 2> ist eine einzelne Einheit ohne Leerzeichen; Sie können einen Abstand zwischen ihm und dem Dateinamen haben. Gleiches gilt für andere Umleitungen, wie z.B. 2>&1 (das Standardfehler auf denselben Ort umleitet wie die Standardausgabe), oder 2>&-, das den Standardfehler schließt, usw. Weitere Details finden Sie unter Umleitungen. (Der obige Code ist eine generische POSIX-ähnliche Shell, nicht spezifisch für bash.)

1 Stimmen

@DavidDoria Sie können grep -i verwenden, oder (in diesem Fall) grep -vi, um die Groß- und Kleinschreibung zu ignorieren.

325voto

mklement0 Punkte 303096

Nota:

  • Diese Antwort geht wahrscheinlich tiefer, als es der Anwendungsfall rechtfertigt, und find 2>/dev/null kann in vielen Situationen gut genug sein . Er kann dennoch von Interesse sein, weil er eine plattformübergreifende Perspektive bietet und einige fortgeschrittene Shell-Techniken diskutiert, um eine möglichst robuste Lösung zu finden, auch wenn die Fälle, vor denen man sich schützen will, weitgehend hypothetisch sind.

Wenn Ihr Schale ist bash o zsh gibt es eine Lösung, die robust und gleichzeitig relativ einfach ist , mit nur POSIX-konforme find Merkmale ; während bash selbst ist nicht Teil von POSIX, aber die meisten modernen Unix-Plattformen bringen es mit, was diese Lösung weitgehend portabel macht:

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

Nota:

  • Wenn Ihr System so konfiguriert ist, dass es Folgendes anzeigt lokalisiert Fehlermeldungen, vorangestellt ist die find ruft unten mit LC_ALL=C ( LC_ALL=C find ... ), um sicherzustellen, dass Englisch Nachrichten gemeldet werden, so dass grep -v 'Permission denied' funktioniert wie vorgesehen. Allerdings werden alle Fehlermeldungen, die hacer werden dann auch in Englisch angezeigt.

  • >(...) ist eine (selten verwendete) Ausgabe Prozesssubstitution die es erlaubt, die Ausgabe umzuleiten (in diesem Fall, stderr Ausgabe ( 2> ) an die stdin des Befehls in >(...) .
    Zusätzlich zu bash y zsh , ksh unterstützt auch sie prinzipiell aber der Versuch, sie mit der Umleitung von stderr wie es hier der Fall ist ( 2> >(...) ), scheint stillschweigend ignoriert zu werden (in ksh 93u+ ).

    • grep -v 'Permission denied' filtert aus ( -v ) alle Zeilen (vom find des Befehls stderr), die die Phrase Permission denied und gibt die restlichen Zeilen auf stderr aus ( >&2 ).

    • Hinweis: Es besteht eine kleine Chance, dass einige der grep kann die Ausgabe von nach find abgeschlossen wird, da der Gesamtbefehl nicht auf den Befehl innerhalb von >(...) zu beenden. Unter bash können Sie dies durch Anhängen von | cat zum Befehl.

Dieser Ansatz ist:

  • robust : grep wird nur angewendet auf Fehlermeldungen (und nicht auf eine Kombination von Dateipfaden und Fehlermeldungen, was zu Fehlalarmen führen könnte), und andere Fehlermeldungen als solche mit verweigerter Berechtigung werden an stderr weitergeleitet.

  • Nebenwirkungsfrei : find wird beibehalten: Die Unfähigkeit, auf mindestens eines der angetroffenen Dateisystemelemente zuzugreifen, führt zu dem Exit-Code 1 (obwohl das nichts darüber aussagt, ob Fehler andere als (auch) verweigerte Genehmigungen).


POSIX-konforme Lösungen:

Vollständig POSIX-konforme Lösungen haben entweder Einschränkungen oder erfordern zusätzlichen Aufwand.

Si find Die Ausgabe des Programms ist in einer ファイル trotzdem (oder ganz unterdrückt), dann wird die Pipeline-basierte Lösung von Die Antwort von Jonathan Leffler ist einfach, robust und POSIX-konform:

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

Beachten Sie, dass die Reihenfolge der Umleitungen wichtig ist: 2>&1 muss kommen erste .

Die Erfassung der stdout-Ausgabe in einer Datei ermöglicht 2>&1 zu senden sólo Fehlermeldungen durch die Pipeline, die grep kann dann eindeutig operieren.

El Der einzige Nachteil ist, dass die Gesamtausgangscode wird die grep Der Befehl , nicht find Das bedeutet in diesem Fall: Wenn es keine Fehler überhaupt nicht oder sólo Bei Fehlern, bei denen die Erlaubnis verweigert wurde, lautet der Exit-Code 1 (Signalisierung Ausfall ), andernfalls (andere Fehler als solche, bei denen die Erlaubnis verweigert wurde) 0 - was das Gegenteil der Absicht ist.
Davon abgesehen, find Der Exit-Code wird ohnehin selten verwendet. da sie oft nur wenige Informationen vermitteln grundlegend Fehler wie die Übergabe eines nicht existierenden Pfades.
Allerdings ist der besondere Fall, dass sogar nur un peu de die Eingabepfade sind aufgrund fehlender Berechtigungen unzugänglich ist reflektiert in find Exit-Code (sowohl in GNU als auch in BSD find ): Wenn ein Fehler bezüglich der verweigerten Berechtigungen für jede der verarbeiteten Dateien, wird der Exit-Code auf 1 .

Die folgende Variante geht darauf ein:

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

Jetzt zeigt der Exit-Code an, ob Fehler aufgetreten sind andere als Permission denied aufgetreten: 1 wenn ja, 0 sonst.
Mit anderen Worten: Der Exit-Code spiegelt nun die wahre Absicht des Befehls wider: Erfolg ( 0 ) wird gemeldet, wenn überhaupt keine Fehler oder sólo Fehler mit verweigerter Erlaubnis aufgetreten.
Dies ist wohl noch besser als das bloße Überholen find Exit-Code durch, wie in der Lösung oben.


gniourf_gniourf in den Kommentaren schlägt eine (immer noch POSIX-konforme) Verallgemeinerung dieser Lösung durch ausgeklügelte Umleitungen die funktioniert auch mit dem Standardverhalten, die Dateipfade nach stdout :

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

Kurz gesagt: Benutzerdefinierter Dateideskriptor 3 wird verwendet, um stdout vorübergehend auszulagern ( 1 ) und stderr ( 2 ), so dass Fehlermeldungen allein kann über Rohrleitungen an grep über stdout.

Ohne diese Umleitungen werden sowohl Daten (Dateipfade) Fehlermeldungen würden über eine Pipeline an grep über stdout, und grep würde dann nicht mehr unterscheiden können zwischen Fehlermeldung Permission denied und eine (hypothetische) Datei, deren Name zufällig Folgendes enthält der Satz Permission denied .

Wie bei der ersten Lösung wird jedoch der folgende Exit-Code gemeldet grep ist, nicht find aber die gleiche Lösung wie oben kann angewendet werden.


Anmerkungen zu den vorhandenen Antworten:

  • Es gibt mehrere Punkte, die zu beachten sind Die Antwort von Michael Brux , find . ! -readable -prune -o -print :

    • Sie erfordert GNU find Vor allem funktioniert es nicht unter macOS. Natürlich, wenn Sie den Befehl nur brauchen, um mit GNU zu arbeiten find wird dies kein Problem für Sie sein.

    • Einige Permission denied Fehler können immer noch Oberfläche: find ! -readable -prune meldet solche Fehler für die Kind Elemente von Verzeichnissen, für die der aktuelle Benutzer über r Erlaubnis, aber es fehlt x (ausführbare) Berechtigung. Der Grund dafür ist, dass das Verzeichnis selbst ist lesbar, -prune wird nicht ausgeführt, und der Versuch des Abstiegs dieses Verzeichnis löst dann die Fehlermeldungen aus. Das heißt, die typisch Fall ist für die r die Erlaubnis, zu fehlen.

    • Hinweis: Der folgende Punkt ist eine Frage der Philosophie und/oder des spezifischen Anwendungsfalls, und Sie können entscheiden, dass er für Sie nicht relevant ist und dass der Befehl Ihren Bedürfnissen gut entspricht, insbesondere wenn Sie einfach Drucken die Wege sind alles, was Sie tun:

      • Wenn Sie konzipieren die Filterung der Fehlermeldungen über verweigerte Genehmigungen als getrennt Aufgabe, auf die Sie sich bewerben möchten jede find Befehl, dann der umgekehrte Ansatz, nämlich proaktiv Verhütung Fehler, für die keine Erlaubnis erteilt wurde, erfordern die Einführung von "Rauschen" in die find Befehl, der ebenfalls Komplexität und Logik mit sich bringt Fallstricke .
      • Der am meisten bewertete Kommentar zu Michaels Antwort (zum Zeitpunkt der Erstellung dieses Artikels) versucht beispielsweise zu zeigen, wie man erweitern. den Befehl durch Einfügen eines -name Filter, wie folgt:
        find . ! -readable -prune -o -name '*.txt'
        Dies bedeutet jedoch no wie vorgesehen funktionieren, da die nachgestellten -print Aktion ist erforderlich (eine Erklärung finden Sie in diese Antwort ). Solche Feinheiten können zu Fehlern führen.
  • Die erste Lösung in Die Antwort von Jonathan Leffler , find . 2>/dev/null > files_and_folders wie er selbst sagt, blindlings schweigt 何れも Fehlermeldungen (und die Umgehung ist umständlich und nicht ganz stabil, wie er auch erklärt). Pragmatisch gesprochen Es ist jedoch die einfachste Lösung da Sie davon ausgehen können, dass alle Fehler auf die Erlaubnis zurückzuführen sind.

  • Antwort des Nebels , sudo find . > files_and_folders , ist prägnant und pragmatisch, aber schlecht geeignet für etwas anderes als nur Drucken Dateinamen aus Sicherheitsgründen: weil Sie als der Wurzel Benutzer, "riskieren Sie, dass Ihr ganzes System durch einen Fehler in find oder eine bösartige Version durcheinander gebracht wird, oder durch einen falschen Aufruf, der etwas unerwartet schreibt, was nicht passieren könnte, wenn Sie dies mit normalen Rechten ausführen würden" (aus einem Kommentar zu Mist's Antwort von tripleee ).

  • Die 2. Lösung in viraptor's Antwort , find . 2>&1 | grep -v 'Permission denied' > some_file birgt das Risiko von Fehlalarmen (da eine Mischung aus stdout und stderr durch die Pipeline geschickt wird), und möglicherweise wird statt der Meldung nicht -verweigerte Fehler über stderr, erfasst sie zusammen mit den Ausgabepfaden in der Ausgabedatei.

5 Stimmen

Nur eine schnelle Frage: Warum verwenden Sie ein Prozess-Substitution und nicht nur ein Pipe: find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?

3 Stimmen

@LéoLéopoldHertz: Wenn Sie die Ausgabe nicht in eine externe Datei umleiten möchten, führen Sie einfach mehr Installationen durch: { find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

3 Stimmen

@LéoLéopoldHertz: Nur dass es POSIX-konform ist. Prozess-Substitutionen >(...) sind spezifisch für Bash.

311voto

Michael Brux Punkte 4066

Verwendung:

find . ! -readable -prune -o -print

oder allgemeiner

find  ! -readable -prune -o  -print
  • um "Keine Berechtigung" zu vermeiden
  • UND unterdrücken Sie (andere) Fehlermeldungen NICHT
  • UND erhalten Sie den Exit-Status 0 ("alle Dateien wurden erfolgreich verarbeitet")

Funktioniert mit: find (GNU findutils) 4.4.2. Hintergrund:

  • Der Test -readable entspricht lesbaren Dateien. Der Operator ! gibt true zurück, wenn der Test falsch ist. Und ! -readable entspricht nicht lesbaren Verzeichnissen (& Dateien).
  • Die Aktion -prune steigt nicht in das Verzeichnis hinab.
  • ! -readable -prune kann übersetzt werden als: Wenn das Verzeichnis nicht lesbar ist, steigen Sie nicht hinein.
  • Der Test -readable berücksichtigt Zugriffssteuerungslisten und andere Berechtigungsartefakte, die der Test -perm ignoriert.

Siehe auch find(1) Manpage für weitere Details.

1 Stimmen

Wie ist dies besser oder schlechter als Jonathans Antwort? Haben beide die gleichen Ausgaben?

6 Stimmen

Die Unterschiede sind bereits erwähnt. Wenn du sie nicht verstehst, dann machen die Antworten vielleicht keinen Unterschied für dich? STDOUT bleibt gleich - STDERR ist anders (du bekommst die anderen Fehlermeldungen mit dieser Antwort) - $? ist anders (ist 0 "erfolgreich" mit dieser Antwort, wenn kein anderer Fehler auftritt - ist immer > 0 "nicht erfolgreich" wenn die Ausgabe zu dev/null umgeleitet wird) - vielleicht benötigt jemand "$?" in einem Skript "korrekt"

5 Stimmen

Ich denke, dies ist die eleganteste Lösung des Threads. Mir gefällt das erfolgreiche Ergebnis $?.

123voto

Fatih Aksu Punkte 3653

Wenn Sie die Suche von der Wurzel "/" aus starten möchten, sehen Sie wahrscheinlich folgende Ausgabe:

find: /./proc/1731/fdinfo: Berechtigung verweigert
find: /./proc/2032/task/2032/fd: Berechtigung verweigert

Dies liegt an den Berechtigungen. Um das zu lösen:

  1. Sie können den Befehl sudo verwenden:

    sudo find /. -name 'zuSuchendeDatei'

Es fordert das Passwort des Super-Benutzers an. Nach der Eingabe des Passworts sehen Sie das gewünschte Ergebnis. Wenn Sie keine Berechtigung haben, den sudo-Befehl zu verwenden (was bedeutet, dass Sie kein Passwort des Super-Benutzers haben), fordern Sie zunächst den Systemadministrator auf, Sie zur sudoers-Datei hinzuzufügen.

  1. Sie können die Standardfehlerausgabe (normalerweise Display/Bildschirm) in eine Datei umleiten und verhindern, dass die Fehlermeldungen auf dem Bildschirm angezeigt werden! Umleitung in eine spezielle Datei /dev/null:

    find /. -name 'zuSuchendeDatei' 2>/dev/null
  2. Sie können die Standardfehlerausgabe (normalerweise Display/Bildschirm) in die Standardausgabe (normalerweise Display/Bildschirm) umleiten und dann mit dem grep-Befehl mit dem Parameter -v "invert" verknüpfen, um die Ausgabelinien nicht anzuzeigen, die die Wortpaare 'Berechtigung verweigert' enthalten:

    find /. -name 'zuSuchendeDatei' 2>&1 | grep -v 'Berechtigung verweigert'

8 Stimmen

@scottmrogowski außer dass es die Frage nicht beantwortet... 1. Bitten Sie den Systemadministrator, Sie zur sudoers-Datei hinzuzufügen. 2. sudo find...

4 Stimmen

Genau das habe ich gesucht!

1 Stimmen

Es ist schon eine Weile her, seitdem ich die richtige Antwort gefunden habe, nachdem ich vier hoch bewertete, seitenlange Antworten gelesen habe, die alle falsch waren. Dankeschön!

107voto

Jeremy Punkte 1029

Ich musste verwenden:

find / -name expect 2>/dev/null

den Namen dessen angeben, was ich finden wollte, und dann sagen, dass alle Fehler auf /dev/null umgeleitet werden sollen

expect ist der Ort des expect-Programms, nach dem ich gesucht habe.

3 Stimmen

@Masi, der Befehl in der Antwort verwendet nicht expect. Stattdessen ist expect einfach der Name der Datei, die dieser Befehl finden wird.

2 Stimmen

Blind das gesamte stderr-Ausgabe umzuleiten, nur um eine einzige Art von Fehlermeldungen zu ignorieren, ist im Allgemeinen keine gute Idee - Sie verlieren dabei alle anderen willkürlichen Fehlermeldungen im Prozess.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X