Hinweis:
* Diese Antwort geht wahrscheinlich tiefer als der Anwendungsfall es rechtfertigt und find 2>/dev/null
kann 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 find
Aufrufen 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 bash
oder istzsh
, gibt es eine Lösung, die robust und relativ einfach ist und nur POSIX-kompatible find
Funktionen verwendet . während bash
sich 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 grep
Ausgabe nach find
Abschluss eintrifft , da der Gesamtbefehl nicht darauf wartet, dass der Befehl im Inneren >(...)
beendet wird. In bash
können Sie dies verhindern, indem Sie | cat
an 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 bash
und zsh
, ksh
sich 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 find
Stderr Strom Befehl), die die Phrase enthalten , Permission denied
und gibt die verbleibenden Zeilen zu Stderr ( >&2
).
Dieser Ansatz ist:
robust : grep
Wird 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 : find
Der 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 find
die 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>&1
muss an erster Stelle stehen .
Stdout Ausgang Einfangen in einer Datei vorne ermöglicht 2>&1
sendet nur Fehlermeldungen , durch die Pipeline, die grep
dann auf eindeutig arbeiten.
Das ist einzige Nachteil , dass der gesamte Code Ausgang wird das sein grep
Gebot , 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 , find
wenn 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. 1
Wenn ja, 0
andernfalls.
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 find
den 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 3
wird temporär Swap stdout (gebraucht 1
) und stderr ( 2
), so dass Fehlermeldungen allein zu geleitet werden kann grep
via stdout.
Ohne diese Umleitungen würden sowohl Daten (Dateipfade) als auch Fehlermeldungen grep
über stdout weitergeleitet und grep
kö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 denied
Fehler können weiterhin auftreten : find ! -readable -prune
Meldet solche Fehler für die untergeordneten Elemente von Verzeichnissen, für die der aktuelle Benutzer zwar über die r
Berechtigung verfügt, jedoch keine x
(ausführbare) Berechtigung besitzt. Der Grund dafür ist , dass , weil das Verzeichnis selbst ist lesbar, -prune
wird nicht ausgeführt, und der Versuch, absteigen in das Verzeichnis löst dann die Fehlermeldungen. Der typische Fall ist jedoch, dass die r
Erlaubnis 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 find
Befehl, 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
-name
Filter wie folgt:
find . ! -readable -prune -o -name '*.txt'
Dies ist jedoch funktioniert nicht wie vorgesehen, weil die hintere -print
Aktion 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_folders
wie 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_file
lä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
?