Hinweis:
* Diese Antwort geht wahrscheinlich tiefer als der Anwendungsfall es rechtfertigt und find 2>/dev/nullkann in vielen Situationen gut genug sein. Es kann weiterhin für eine plattformübergreifende Perspektive und für die Erörterung einiger fortschrittlicher Shell-Techniken von Interesse sein, um eine möglichst robuste Lösung zu finden, auch wenn die vorgeschützten Fälle weitgehend hypothetisch sind.
* Wenn Ihr System so konfiguriert ist, dass lokalisierte Fehlermeldungen angezeigt werden , stellen Sie den folgenden findAufrufen LC_ALL=C( LC_ALL=C find ...) voran, um sicherzustellen, dass englische Nachrichten gemeldet werden, damit dies grep -v 'Permission denied'wie beabsichtigt funktioniert. Unweigerlich jedoch keine Fehlermeldungen , die Sie angezeigt bekommen dann auch in englischer Sprache.
Wenn Ihre Shell bashoder istzsh , gibt es eine Lösung, die robust und relativ einfach ist und nur POSIX-kompatible findFunktionen verwendet . während bashsich die nicht Teil von POSIX, die meisten modernen Unix - Plattformen kommen mit ihm ist, so dass diese Lösung weit tragbar:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Hinweis: Es besteht eine geringe Wahrscheinlichkeit, dass ein Teil der grepAusgabe nach find Abschluss eintrifft , da der Gesamtbefehl nicht darauf wartet, dass der Befehl im Inneren >(...)beendet wird. In bashkönnen Sie dies verhindern, indem Sie | catan den Befehl anhängen .
>(...)ist eine (selten eingesetzt) Ausgabeprozess Substitution , die ausgegeben (in diesem Fall Umleiten erlaubt Stderr Ausgang ( 2>) an die stdin des Innenbefehls >(...).
Neben bashund zsh, kshsich unterstützt , als auch im Prinzip , sondern zu versuchen , sie mit Umleitung zu kombinieren aus stderr2> >(...) scheint , wie hier ( ) gemacht, stillschweigend ignoriert zu werden (in ksh 93u+).
grep -v 'Permission denied'filtert aus ( -v) alle Zeilen (aus dem findStderr Strom Befehl), die die Phrase enthalten , Permission deniedund gibt die verbleibenden Zeilen zu Stderr ( >&2).
Dieser Ansatz ist:
robust : grepWird nur auf Fehlermeldungen angewendet (und nicht auf eine Kombination aus Dateipfaden und Fehlermeldungen, die möglicherweise zu Fehlalarmen führen), und andere Fehlermeldungen als die mit Berechtigungen verweigerten werden an stderr weitergeleitet.
Nebenwirkungsfrei : findDer Exit-Code bleibt erhalten: Die Unfähigkeit, auf mindestens eines der gefundenen Dateisystemelemente zuzugreifen, führt zu einem Exit-Code 1(obwohl dies Ihnen nicht sagt, ob (auch) andere Fehler als die mit Berechtigung verweigerten aufgetreten sind).
POSIX-konforme Lösungen:
Vollständig POSIX-kompatible Lösungen weisen entweder Einschränkungen auf oder erfordern zusätzliche Arbeit.
Wenn finddie Ausgabe ohnehin in einer Datei erfasst (oder ganz unterdrückt) werden soll, ist die Pipeline-basierte Lösung aus Jonathan Lefflers Antwort einfach, robust und POSIX-konform:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Beachten Sie, dass die Reihenfolge der Weiterleitungen wichtig ist: 2>&1muss an erster Stelle stehen .
Stdout Ausgang Einfangen in einer Datei vorne ermöglicht 2>&1sendet nur Fehlermeldungen , durch die Pipeline, die grepdann auf eindeutig arbeiten.
Das ist einzige Nachteil , dass der gesamte Code Ausgang wird das sein grepGebot , nicht find‚s, was in diesem Fall bedeutet: Wenn es keine Fehler bei allen oder nur die Erlaubnis verweigert Fehler, wird der Exit - Code werden (Meldeausfall1 ), andernfalls ( andere Fehler als die, denen die Erlaubnis verweigert wurde) - das ist das Gegenteil der Absicht. Der Exit-Code wird jedoch ohnehin selten verwendet , da er häufig nur wenige Informationen über grundlegende Fehler wie das Übergeben eines nicht vorhandenen Pfads hinaus übermittelt .
Allerdings ist der konkrete Fall auch nur einiger0
find
der Eingangswege aufgrund von Berechtigungen Mangel unzugänglich sein wird in reflektiert find‚s Exit - Code (in beiden GNU und BSD , findwenn ein Berechtigungs verweigert Fehler tritt für:) jede der Dateien verarbeitet, der Exit - Code wird auf 1.
Die folgende Variante spricht das an:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Der Exit-Code gibt nun an, ob andere als die Permission denied aufgetretenen Fehler aufgetreten sind. 1Wenn ja, 0andernfalls.
Mit anderen Worten: Der Exit-Code spiegelt jetzt die wahre Absicht des Befehls wider: success ( 0) wird gemeldet, wenn überhaupt keine Fehler aufgetreten sind oder nur Fehler ohne Berechtigung aufgetreten sind.
Dies ist wohl sogar besser, als nur findden Exit-Code durchzuleiten, wie in der Lösung oben.
gniourf_gniourf in den Kommentaren schlägt eine (immer noch POSIX-kompatible) Verallgemeinerung dieser Lösung unter Verwendung ausgefeilter Umleitungen vor , die auch mit dem Standardverhalten des Druckens der Dateipfade nach stdout funktioniert :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
Kurz gesagt: Descriptor Benutzerdefinierte Datei 3wird temporär Swap stdout (gebraucht 1) und stderr ( 2), so dass Fehlermeldungen allein zu geleitet werden kann grepvia stdout.
Ohne diese Umleitungen würden sowohl Daten (Dateipfade) als auch Fehlermeldungen grepüber stdout weitergeleitet und grepkönnten dann nicht zwischen Fehlermeldungen Permission denied und einer (hypothetischen) Datei unterscheiden, deren Name zufällig die Phrase enthält Permission denied.
Wie in der ersten Lösung lautet der gemeldete Exit-Code jedoch grep's, nicht find' s, sondern es kann der gleiche Fix wie oben angewendet werden.
Anmerkungen zu den vorhandenen Antworten:
Es gibt mehrere Punkte beachten Michael Brux Antwort , find . ! -readable -prune -o -print:
Es erfordert GNU find ; Insbesondere wird es unter MacOS nicht funktionieren. Wenn Sie den Befehl nur für die Arbeit mit GNU benötigen find, ist dies natürlich kein Problem für Sie.
Einige Permission deniedFehler können weiterhin auftreten : find ! -readable -pruneMeldet solche Fehler für die untergeordneten Elemente von Verzeichnissen, für die der aktuelle Benutzer zwar über die rBerechtigung verfügt, jedoch keine x(ausführbare) Berechtigung besitzt. Der Grund dafür ist , dass , weil das Verzeichnis selbst ist lesbar, -prunewird nicht ausgeführt, und der Versuch, absteigen in das Verzeichnis löst dann die Fehlermeldungen. Der typische Fall ist jedoch, dass die rErlaubnis fehlt.
Hinweis: Der folgende Punkt ist eine Frage der Philosophie und / oder des spezifischen Anwendungsfalls. Sie können entscheiden, dass er für Sie nicht relevant ist und dass der Befehl Ihren Anforderungen gut entspricht, insbesondere wenn Sie nur die Pfade drucken :
- Wenn Sie das Filtern der Fehlermeldungen mit verweigerter Berechtigung als separate Aufgabe konzipieren, die Sie auf jeden
find Befehl anwenden möchten, erfordert der umgekehrte Ansatz, Fehler mit verweigerter Berechtigung proaktiv zu verhindern, das Einfügen von "Rauschen" in den findBefehl, der ebenfalls eingeführt wird Komplexität und logische Fallstricke .
- Zum Beispiel, die meist up-gestimmt Kommentar auf Michaels Antwort (zum Zeitpunkt des Schreibens) versucht zu zeigen , wie zu erweitern den Befehl durch einen mit
-nameFilter wie folgt:
find . ! -readable -prune -o -name '*.txt'
Dies ist jedoch funktioniert nicht wie vorgesehen, weil die hintere -printAktion erforderlich (Eine Erklärung finden Sie in dieser Antwort ). Solche Feinheiten können Fehler verursachen.
Die erste Lösung in Jonathan Leffler Antwort , find . 2>/dev/null > files_and_folderswie er selbst sagt, zum Schweigen bringt blind alle Fehlermeldungen (und die Abhilfe ist umständlich und nicht ganz robust, wie er erklärt auch). Pragmatisch gesehen ist dies jedoch die einfachste Lösung , da Sie möglicherweise davon ausgehen können, dass alle Fehler mit der Berechtigung zusammenhängen.
Nebel Antwort , sudo find . > files_and_folders, ist prägnant und pragmatisch, aber schlecht beraten für etwas anderes als nur das Drucken von Dateinamen , aus Sicherheitsgründen: weil Sie als laufen root Benutzer „ , riskieren Sie Ihr gesamtes System mit durch einen Fehler in Fund werden verkorkste oder eine böswillige Version oder ein falscher Aufruf, der etwas Unerwartetes schreibt, was nicht passieren könnte, wenn Sie dies mit normalen Berechtigungen ausführen "(aus einem Kommentar zur Antwort von Mist durch Tripleee ).
Die zweite Lösung in viraptor Antwort , find . 2>&1 | grep -v 'Permission denied' > some_fileläuft das Risiko von Fehlalarmen (durch eine Mischung aus stdout und stderr durch die Pipeline zu senden), und möglicherweise anstelle der Berichterstattung nicht -permission verweigern Fehler über stderr, erfasst sie neben den Ausgangspfaden in der Ausgabedatei.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?