Wie kann ich alle "Berechtigungsverweigerungs" -Nachrichten von "Suchen" ausschließen?

794

Ich muss alle Nachrichten verbergen, denen die Berechtigung verweigert wurde vor:

find . > files_and_folders

Ich experimentiere, wenn eine solche Nachricht entsteht. Ich muss alle Ordner und Dateien sammeln, zu denen es nicht kommt.

Ist es möglich, die Berechtigungsstufen auf die files_and_foldersDatei zu lenken ?

Wie kann ich die Fehler gleichzeitig ausblenden?

Léo Léopold Hertz 준영
quelle

Antworten:

259

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.

mklement0
quelle
4
Nur eine kurze Frage: Warum verwenden Sie eine Prozessersetzung und nicht nur eine Pipe find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Wenn Sie nicht in eine externe Datei ausgeben möchten, machen Sie einfach mehr Sanitär:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Nur dass es POSIX-konform ist. Prozesssubstitutionen >(...)sind Bash-spezifisch.
gniourf_gniourf
2
Ich bin mir nicht sicher, ob die Beibehaltung des Exit-Codes von findhervorgehoben und beworben werden sollte: findDer Exit-Code von ist notorisch nutzlos. Hier wird es sehr wahrscheinlich ungleich Null sein (und das nutzlos).
gniourf_gniourf
3
POSIX benötigt ausdrücklich die execute/searchDateimodus-Berechtigung, um ein Verzeichnis zu durchsuchen (die Inodes der enthaltenen Dateien abzurufen). findDies geschieht, um in ein Unterverzeichnis abzusteigen (zusätzlich zur readBerechtigung zum Auflisten der Dateien in einem Verzeichnis). Dies ist kein "Fehler" oder "Portierungsfehler".
Wjordan
542

Verwenden:

find . 2>/dev/null > files_and_folders

Dies verbirgt Permission deniednatürlich nicht nur die Fehler, sondern alle Fehlermeldungen.

Wenn Sie wirklich andere mögliche Fehler behalten möchten, z. B. zu viele Hops auf einem Symlink, aber nicht die verweigerten, dann müssen Sie wahrscheinlich davon ausgehen, dass Sie nicht viele Dateien mit dem Namen "Berechtigung verweigert" haben. und versuche:

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

Wenn Sie nur Standardfehler filtern möchten, können Sie die aufwändigere Konstruktion verwenden:

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

Die E / A-Umleitung des findBefehls lautet : 2>&1 > files_and_folders |. Die Pipe leitet die Standardausgabe an den grepBefehl weiter und wird zuerst angewendet. Der 2>&1sendet den Standardfehler an dieselbe Stelle wie die Standardausgabe (die Pipe). Das > files_and_folderssendet die Standardausgabe (aber nicht den Standardfehler) an eine Datei. Das Nettoergebnis ist, dass Nachrichten, die auf Standardfehler geschrieben wurden, über die Pipe gesendet werden und die reguläre Ausgabe von findin die Datei geschrieben wird. Das grepfiltert die Standardausgabe (Sie können entscheiden, wie selektiv sie sein soll, und muss möglicherweise die Schreibweise je nach Gebietsschema und Betriebssystem ändern) und das Finale>&2bedeutet, dass die überlebenden Fehlermeldungen (in die Standardausgabe geschrieben) erneut zum Standardfehler gehen. Die endgültige Umleitung kann am Terminal als optional angesehen werden, wäre jedoch eine sehr gute Idee, sie in einem Skript zu verwenden, damit bei Standardfehlern Fehlermeldungen angezeigt werden.

Es gibt endlose Variationen zu diesem Thema, je nachdem, was Sie tun möchten. Dies funktioniert auf jeder Unix-Variante mit jedem Bourne-Shell-Derivat (Bash, Korn,…) und jeder POSIX-kompatiblen Version von find.

Wenn Sie sich an die spezifische Version findIhres Systems anpassen möchten , stehen möglicherweise alternative Optionen zur Verfügung. findInsbesondere GNU verfügt über eine Vielzahl von Optionen, die in anderen Versionen nicht verfügbar sind. Eine solche Option finden Sie in der derzeit akzeptierten Antwort.

Jonathan Leffler
quelle
9
Wenn Sie wie ich sind, beachten Sie, dass Platzmangel wichtig ist! 2>/dev/null, ohne Platz!
Nik
20
Das 2>ist eine einzelne Einheit ohne Leerzeichen; Sie können ein Leerzeichen zwischen dem Dateinamen und dem Dateinamen einfügen. Ähnlich verhält es sich mit anderen Umleitungen, z. B. 2>&1(die den Standardfehler an dieselbe Stelle umleiten wie die Standardausgabe) oder 2>&-die den Standardfehler schließen usw. Weitere Informationen finden Sie unter Umleitungen . (Der obige Code ist eine generische POSIX-ähnliche Shell, nicht spezifisch für bash.)
Jonathan Leffler
3
Ich musste ein großes P verwenden, weil mein Terminal dies ausgeben würde: find. 2> & 1 | grep -v 'Erlaubnis verweigert'
David Doria
4
Wie ist das eine akzeptable Lösung? 1) Sie leiten ALLE Fehler nach dev / null um. 2) Sie filtern eine explizite Fehlerzeichenfolge !! Abhängig davon ist bekanntermaßen spröde und was ist, wenn sich Ihre Datei in einem Verzeichnis mit dem Namen "Berechtigung verweigert" befand? Hoppla!
Gunchars
10
Ich lehne es ab, Fehlerzeichenfolgen zu erfassen, um die Programmausgabe zu ändern. Es wird die meiste Zeit funktionieren, aber einfach ist nicht die richtige Lösung (finden Sie mit Dauerwellen unten ist). Um Ihnen ein Beispiel zu geben, warum dies unter OSX nicht funktioniert, da der Fehler "Berechtigung verweigert" lautet. Gleiches gilt für jedes andere System, bei dem es sogar winzige Unterschiede in der
Fehlerzeichenfolge gibt
285

Verwenden:

find . ! -readable -prune -o -print

oder allgemeiner

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • um "Erlaubnis verweigert" zu vermeiden
  • UND unterdrücken Sie NICHT (andere) Fehlermeldungen
  • UND Exit-Status 0 erhalten ("Alle Dateien werden erfolgreich verarbeitet")

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

  • Der -readableTest stimmt mit lesbaren Dateien überein. Der !Operator gibt true zurück, wenn test false ist. Und ! -readablestimmt mit nicht lesbaren Verzeichnissen (& Dateien) überein.
  • Die -pruneAktion wird nicht in ein Verzeichnis verschoben.
  • ! -readable -prune kann übersetzt werden in: Wenn das Verzeichnis nicht lesbar ist, steigen Sie nicht in das Verzeichnis ab.
  • Der -readableTest berücksichtigt Zugriffssteuerungslisten und andere Berechtigungsartefakte, die der -permTest ignoriert.

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

Michael Brux
quelle
6
Die Unterschiede sind bereits erwähnt. Wenn Sie nicht verstehen, machen die Antworten für Sie vielleicht keinen Unterschied? STDOUT ist das gleiche - STDERR ist anders (Sie erhalten die anderen Fehlermeldungen mit dieser Antwort) - $? ist anders (ist 0 "erfolgreich" bei dieser Antwort, wenn kein anderer Fehler auftritt - ist immer> 0 "nicht erfolgreich", wenn auf dev / null umgeleitet wird) - vielleicht braucht jemand "korrekt" $? in einem Skript
Michael Brux
6
@Masi der offensichtlichste Fehler ist, dass Jonathans Antwort (grep -v) den Dateinamen ausschließt, der 'Erlaubnis verweigert' enthält :)
Obst
65
Ich halte es für angebracht, hier hinzuzufügen, dass, wenn Sie einige andere Suchkriterien hinzufügen müssen, dies getan werden sollte mit -o:find . ! -readable -prune -o -name '*.txt'
Tempestadept
22
Beachten Sie, dass POSIX findnicht -readableals Option enthalten ist. Das gilt auch nicht findfür BSD und damit für Mac OS X (bei anderen Systemen bin ich mir nicht sicher). findWenn Sie also GNU garantiert haben, funktioniert dies hervorragend, aber es ist nicht offensichtlich, wie Sie dies anpassen können, wenn Sie nicht garantieren können, dass auf dem System GNU findinstalliert ist. (Es wird gut unter Linux funktionieren; es kann anderswo funktionieren oder nicht.)
Jonathan Leffler
6
find . ! -readable -prune -o -name '*.txt'scheint unter Ubuntu 14.04 mit find 4.2.2 nicht zu funktionieren. Es scheint die -name. Aus irgendeinem seltsamen Grund habe ich Erfolg mitfind . \( ! -readable -prune \) -o -name '*.txt' -print
con-f-use
110

Wenn Sie die Suche von root "/" aus starten möchten, werden Sie wahrscheinlich folgende Ausgaben sehen:

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

Es ist wegen der Erlaubnis. Um dies zu lösen:

  1. Sie können den Befehl sudo verwenden:

    sudo find /. -name 'toBeSearched.file'

Es fragt nach dem Passwort des Superusers. Wenn Sie das Passwort eingeben, sehen Sie das Ergebnis, was Sie wirklich wollen. Wenn Sie nicht berechtigt sind, den Befehl sudo zu verwenden, was bedeutet, dass Sie kein Superuser-Passwort haben, bitten Sie zuerst den Systemadministrator, Sie zur sudoers-Datei hinzuzufügen.

  1. Sie können die Standardfehlerausgabe von (Allgemein Anzeige / Bildschirm) in eine Datei umleiten und vermeiden, dass die Fehlermeldungen auf dem Bildschirm angezeigt werden! Weiterleitung in eine spezielle Datei / dev / null:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. Sie können die Standardfehlerausgabe von (Allgemein Anzeige / Bildschirm) auf Standardausgabe (Allgemein Anzeige / Bildschirm) umleiten und dann mit dem Befehl grep mit dem Parameter -v "invertieren" weiterleiten, um die Ausgabezeilen mit der Berechtigung "Berechtigung verweigert" nicht anzuzeigen. Wortpaare:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
Fatih Aksu
quelle
7
@scottmrogowski, außer dass die Frage nicht beantwortet wird ... 1. Bitten Sie den Systemadministrator, Sie zur sudoers-Datei hinzuzufügen. 2.sudo find...
Stephen
1
genau das, wonach ich gesucht habe!
DankMasterDan
92

Ich musste verwenden:

find / -name expect 2>/dev/null

Geben Sie den Namen dessen an, was ich finden wollte, und teilen Sie ihm dann mit, dass alle Fehler nach / dev / null umgeleitet werden sollen

Erwarten Sie, dass es sich um den Speicherort des erwarteten Programms handelt, nach dem ich gesucht habe.

Jeremy
quelle
3
@Masi, der Befehl in der Antwort wird nicht verwendet expect. Stattdessen expectist einfach der Name der Datei, die dieser Befehl zu finden versucht.
Dhruv Kapoor
2
Das blinde Umleiten aller stderr-Ausgaben, um nur eine einzelne Klasse von Fehlermeldungen zu ignorieren, ist im Allgemeinen eine schlechte Idee - Sie verlieren dabei alle anderen willkürlichen Fehler.
Josip Rodin
59

Pipe stderrto /dev/nullmit 2> / dev / null

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

Matt
quelle
2
Dies funktioniert auch unter Mac OSX einwandfrei. Oder sogarfind . -name '...' -print 2>/dev/null
Shadowsheep
30

Sie können auch die Prädikate -permund verwenden -prune, um zu vermeiden, dass Sie in unlesbare Verzeichnisse absteigen (siehe auch Entfernen von Ausdruckanweisungen "Berechtigung verweigert" aus dem Suchprogramm? - Unix & Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
sdaau
quelle
4
-perm -g+r,u+r,o+rStimmt nur mit Dateien überein, für die die r(Lese-) Berechtigung für alle drei Sicherheitsprinzipale der Datei festgelegt wurde. Dies hat keine direkte Beziehung dazu, ob der aktuelle Benutzer diese Datei lesen kann oder nicht. Es kann sowohl Dateien übersehen, die der aktuelle Benutzer lesen kann , als auch Dateien abgleichen, die er nicht lesen kann.
mklement0
Ich denke find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printwäre die gute Lösung.
Mattia72
2
@ Mattia72: Nein, ist es grundsätzlich unmöglich , vollständig zu emulieren -readablemit -perm- meine vorherigen Kommentar und betrachten Sie dieses Beispiel sehen: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rdruckt file, weil seine Benutzer gelesen Bit gesetzt, aber es bezieht sich auf die der nobodyBenutzer nicht den aktuellen Benutzer. Der aktuelle Benutzer kann diese Datei nicht lesen. versuche es cat file. Siehe auch: diese Antwort von mir.
mklement0
23

Standardfehler umleiten. Wenn Sie beispielsweise bash auf einem Unix-Computer verwenden, können Sie den Standardfehler folgendermaßen nach / dev / null umleiten:

find . 2>/dev/null >files_and_folders
Jason Coco
quelle
20

Während die oben genannten Ansätze den Fall für Mac OS X nicht behandeln, da Mac Os X -readableSwitches nicht unterstützt , können Sie auf diese Weise Fehler in Ihrer Ausgabe vermeiden, bei denen die Berechtigung verweigert wurde. Dies könnte jemandem helfen.

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

Wenn Sie einen anderen Befehl verwenden find, um beispielsweise die Größe von Dateien mit einem bestimmten Muster in einem Verzeichnis zu ermitteln 2>/dev/null, funktioniert dies weiterhin wie unten gezeigt.

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

Dies gibt die Gesamtgröße der Dateien eines bestimmten Musters zurück. Beachten Sie den 2>/dev/nullBefehl am Ende des Suchvorgangs.

Bunti
quelle
Schöne Bindung an das OS X! Jonathans Antwort erklärt den Teil 2>/dev/null. Können Sie bitte den Teil erklären -exec du -ch {} + 2>/dev/null | grep total$.
Léo Léopold Hertz 2
1
@Masi Sie können einen beliebigen Befehl mit -execOption verwenden, um weitere Aktionen für die vom findBefehl gefundenen Dateien oder Verzeichnisse auszuführen . du -ch file_patternberechnet die Größe jeder übereinstimmenden Datei file_patternund die letzte Zeile dieser Ausgabe ist die Gesamtsumme aller Dateien, die mit der übereinstimmen file_pattern. Siehe Manpage für du. grep totalfiltert nur die Zeile, die die Gesamtsumme extrahiert (dies ist die letzte Zeile).
Bunti
13

Diese Fehler werden in der Standardfehlerausgabe (fd 2) ausgedruckt. Um sie herauszufiltern, leiten Sie einfach alle Fehler nach / dev / null um:

find . 2>/dev/null > some_file

oder verbinden Sie zuerst stderr und stdout und suchen Sie dann die spezifischen Fehler heraus:

find . 2>&1 | grep -v 'Permission denied' > some_file
Viraptor
quelle
11

Einfache Antwort:

find . > files_and_folders 2>&-

2>&-schließt ( -) den Standard-Fehlerdateideskriptor ( 2), damit alle Fehlermeldungen stummgeschaltet werden.

  • Der Exit-Code wird weiterhin angezeigt, 1wenn Permission deniedandernfalls Fehler gedruckt würden

Robuste Antwort für GNU find:

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

Führen Sie zusätzliche Optionen zu , finddass -prune(verhindern Abstieg in) , aber immer noch ein -printbeliebiges Verzeichnis ( ), die nicht ( ) beide haben und Berechtigungen, oder ( ) jede andere Datei.-typed\!-readable-executable-o-print

Robuste Antwort, die mit jedem POSIX-kompatiblen findGerät (GNU, OSX / BSD usw.) funktioniert.

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

Verwenden Sie eine Pipeline , um den Standardfehlerstrom an zu übergeben grep, und entfernen Sie alle Zeilen, die die 'Permission denied'Zeichenfolge enthalten.

LC_ALL=CStellt die POSIX locale eine Verwendung von Umgebungsvariablen , 3>&2 2>&1 1>&3und 3>&2 2>&1 Duplikat - Datei - Deskriptoren , um die Standard - Rohr-Fehlerstrom auf grep, und [ $? = 1 ]Verwendungen []der Fehlercode zurückgegeben , indem invertieren grepdas ursprüngliche Verhalten anzunähern , der find.

  • Filtert auch 'Permission denied'Fehler aufgrund der Ausgabeumleitung (z. B. wenn die files_and_foldersDatei selbst nicht beschreibbar ist).
wjordan
quelle
Wie denkst du über JordiFerrans Antwortvorschlag? - - Kannst du deine Antwort damit vergleichen?
Léo Léopold Hertz 25
2
Das angegebene Shell-Skript dieser Antwort ist nicht universell (listet nur Verzeichnisse auf, die mit $ {m_find_name} übereinstimmen) und enthält mehrere Optionen, die für die Frage nicht relevant sind (nice, / home *, -maxdepth 5, -follow). Diese Antwort befasst sich mit dem spezifischen Problem des Lesens von lesbaren, aber nicht ausführbaren Verzeichnissen, wobei der allgemeine Zweck beibehalten wird.
Wjordan
1
@wjordan: Danke. Ich habe meine Kommentare entfernt, aber ein Punkt gilt immer noch: Die -permbasierte Lösung ist es nicht wert, vorgestellt zu werden, da sie grundlegender als im Zitat angegeben etwas anderes als beabsichtigt bewirkt : Es handelt sich um einen rein dateizentrierten Test, der sich auf den Eigentümer der Datei bezieht und Gruppe, von denen keine eine garantierte Beziehung zu dem Benutzer hat, der den Befehl aufruft (siehe meine Antwort . Es sieht so aus, als ob Ihre überarbeitete GNU-Lösung jetzt keine Fehler
abfängt, denen die
Ich erkenne die von Ihnen verwendete Syntax nicht (weder als GNU noch als BSD), aber lassen Sie mich meinen Standpunkt anhand eines in sich geschlossenen Beispiels veranschaulichen: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rDrucke file, da das Lesebit des Benutzers gesetzt ist, sich aber auf den nobodyBenutzer bezieht , nicht der aktuelle Benutzer. Der aktuelle Benutzer kann diese Datei nicht lesen. versuche es cat file.
mklement0
1
@ mklement0 danke für die Diskussion, ich habe es geschafft, das Verhalten zu erzeugen, das Sie in einem anderen Test beschrieben haben (ich weiß nicht, was ich beim ersten Mal falsch gemacht habe), es scheint, dass -permes nicht funktioniert, um die aktuellen Berechtigungen des Benutzers zu bestimmen. Diese Alternative wurde aus dieser Antwort entfernt.
Wjordan
4

Um nur die Warnungen zu vermeiden, denen die Berechtigung verweigert wurde, weisen Sie find an, die nicht lesbaren Dateien zu ignorieren, indem Sie sie aus der Suche entfernen. Fügen Sie Ihrem Fund einen Ausdruck als ODER hinzu, z

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

Dies sagt meistens zu (eine unlesbare Datei abgleichen und aus der Liste entfernen ) ODER (einen Namen wie * .jbd abgleichen und [mit ls] anzeigen) . (Denken Sie daran, dass die Ausdrücke standardmäßig UND-verknüpft sind, es sei denn, Sie verwenden -oder.) Sie benötigen die -ls im zweiten Ausdruck, oder find fügt möglicherweise eine Standardaktion hinzu, um eine der beiden Übereinstimmungen anzuzeigen, die Ihnen auch alle nicht lesbaren Dateien anzeigt .

Wenn Sie jedoch nach echten Dateien auf Ihrem System suchen, gibt es normalerweise keinen Grund, in / dev zu suchen, das viele, viele Dateien enthält. Fügen Sie daher einen Ausdruck hinzu, der dieses Verzeichnis ausschließt, z.

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

Also (nicht lesbare Datei abgleichen und von Liste entfernen ) ODER (Pfad / Entwickler abgleichen und von Liste entfernen ) ODER (Datei wie * .jbd abgleichen und anzeigen) .

simpleuser
quelle
4

verwenden

sudo find / -name file.txt

Es ist dumm (weil Sie die Suche erhöhen) und unsicher, aber viel kürzer zu schreiben.

Nebel
quelle
Sie suchen hier das gesamte Dateisystem, also meinen Sie damit "die Suche erhöhen". Warum nennst du es unsicher? Weil es das ganze Dateisystem durchsucht?
Léo Léopold Hertz 준영
2
Weil sudo den Befehl find mit Root-Berechtigungen ausführt, was im Grunde eine schlechte Idee ist. Segregation und Grundsätze der geringsten Privilegien werden verletzt.
Nebel
3
Die "Erhebung" hier ist von den Privilegien, mit zu wurzeln sudo. Sie riskieren, dass Ihr gesamtes System durch einen Fehler findoder eine böswillige Version oder einen falschen Aufruf, der etwas Unerwartetes schreibt , durcheinander gebracht wird. Dies könnte nicht passieren, wenn Sie dies mit normalen Berechtigungen ausführen.
Tripleee
2

Keine der oben genannten Antworten hat bei mir funktioniert. Was ich im Internet finde, konzentriert sich auf: Fehler verbergen. Keiner behandelt den Prozess-Rückkehrcode / Exit-Code ordnungsgemäß. Ich benutze den Befehl find in Bash-Skripten, um einige Verzeichnisse zu finden und dann deren Inhalt zu überprüfen. Ich bewerte den Erfolg der Befehlsfindung anhand des Exit-Codes: Ein Wert von Null funktioniert, andernfalls schlägt er fehl.

Die Antwort von Michael Brux funktioniert manchmal. Aber ich habe ein Szenario, in dem es fehlschlägt! Ich habe das Problem entdeckt und selbst behoben. Ich muss Dateien beschneiden, wenn:

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

Das Hauptproblem hier ist: UND / ODER. Eine gute vorgeschlagene Bedingungssequenz, die ich gelesen habe, ist:

-type d ! -readable ! -executable -prune

Das funktioniert nicht immer. Dies bedeutet, dass eine Bereinigung ausgelöst wird, wenn ein Match ist:

it is directory AND no read access AND no execute access

Diese Folge von Ausdrücken schlägt fehl, wenn Lesezugriff gewährt wird, jedoch kein Ausführungszugriff.

Nach einigen Tests wurde mir dies klar und ich änderte meine Shell-Skriptlösung in:

nice find / home * / -maxdepth 5 -follow \
    \ (-type d -a ! \ (-readable -a -executable \) \) -prune \
    -o \
    \ (-type d -a -readable -a - ausführbare Datei -a -name "$ {m_find_name}" \) -print

Der Schlüssel hier ist, das "nicht wahr" für einen kombinierten Ausdruck zu platzieren:

has read access AND has execute access

Andernfalls hat es keinen vollständigen Zugriff, was bedeutet: Beschneiden. Dies hat sich für mich in einem Szenario bewährt, in dem zuvor vorgeschlagene Lösungen fehlgeschlagen sind.

Ich gebe unten technische Details für Fragen im Kommentarbereich. Ich entschuldige mich, wenn die Details übertrieben sind.

  • ¿Warum den Befehl nice verwenden? Ich habe die Idee hier . Anfangs dachte ich, es wäre schön, die Prozesspriorität zu reduzieren, wenn man ein gesamtes Dateisystem betrachtet. Mir wurde klar, dass es für mich keinen Sinn macht, da mein Skript auf wenige Verzeichnisse beschränkt ist. Ich habe -maxdepth auf 3 reduziert.
  • ¿Warum in / home * / suchen? Dies ist für diesen Thread nicht relevant. Ich installiere alle Anwendungen von Hand über Quellcode-Kompilierung mit nicht privilegierten Benutzern (nicht root). Sie werden in "/ home" installiert. Ich kann mehrere Binärdateien und Versionen zusammenleben lassen. Ich muss alle Verzeichnisse lokalisieren, überprüfen und auf Master-Slave-Weise sichern. Ich kann mehr als ein "/ home" haben (mehrere Festplatten laufen auf einem dedizierten Server).
  • ¿Warum -follow verwenden? Benutzer können symbolische Links zu Verzeichnissen erstellen. Es hängt von der Nützlichkeit ab, ich muss die gefundenen absoluten Pfade aufzeichnen.
Jordi Ferran
quelle
Vielen Dank für Ihre Antwort und nette Beobachtungen! Ich habe hier ein Kopfgeld eröffnet, um eine bessere Vorschau Ihrer Antwort zu erhalten. Ich denke, es ist eine schöne Erkenntnis, die den Lese- und Ausführungszugriff nicht verhindert. - - Können Sie bitte erklären, warum Sie niceund verwenden find $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz 22
2
Der Shell - Skript angegeben als nicht für allgemeine Zwecke (nur Listen Verzeichnisse Matching ${m_find_name}) und enthält mehrere Optionen nicht relevant für die Frage ( nice, /home*, -maxdepth 5, -follow). Ich habe eine Antwort hinzugefügt, die das spezifische Problem des Filterns lesbarer, aber nicht ausführbarer Verzeichnisse präziser behandelt und gleichzeitig allgemeiner Zweck bleibt.
Wjordan
2

Sie können das grep -v invert-match verwenden

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

so was:

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

Sollte zur Magie

Leonardo Hermoso
quelle
2

- = Für MacOS = -

Erstellen Sie einen neuen Befehl mit dem Alias: Fügen Sie einfach die Zeile ~ / .bash_profile hinzu:

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

und im neuen Terminalfenster können Sie es aufrufen:

$ file=<filename or mask>; search

zum Beispiel:

$ file = etc; Suche

Jan aka uptech
quelle
1

Wenn Sie CSH oder TCSH verwenden, finden Sie hier eine Lösung:

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

Wenn Sie eine Ausgabe an das Terminal wünschen:

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

Wie in den häufig gestellten Fragen zu "csh-whynot" beschrieben, sollten Sie CSH jedoch nicht verwenden.

Kayle Sawyer
quelle
Ich möchte alle txt-Dateien durchsuchen und versteckte Dateien / Verzeichnisse ausschließen und die zu druckende Meldung "Berechtigung verweigert" weglassen. Ich benutze csh Shell. Ich habe unten Befehle verwendet und sie funktionieren nicht zu finden. -type f -iname " .txt" -not -path '* / \. '| egrep -v "Berechtigung verweigert" finden. -type f -iname " .txt" -not -path '* / \. '2> / dev / null Unter Fehler geraten. find: Pfade müssen vor dem Ausdruck stehen: 2 Verwendung: find [-H] [-L] [-P] [-Olevel] [-D Hilfe | Baum | Suche | Statistik | Raten | Opt | Exec] [Pfad ...] [Ausdruck]
Yadav