Wie beherrsche ich den UNIX-Befehl find?


11

Ich denke, ich bin ziemlich fortgeschritten in der Verwendung von find, aber jedes Mal, wenn ich es benutze, kann ich mich für mein ganzes Leben nicht an die Methode erinnern, die Option -exec zu schließen. Ich verbringe jedes Mal viel Zeit mit Lesen, wenn ich es benutze. Benutze ich es einfach nicht genug oder erwarte ich zu viel von mir selbst? Beginnen wir mit einem typischen Beispiel, das mich frustriert.

Die Verzeichnisstruktur enthält Dateien mit allen falschen Berechtigungen, versteckte Dateien, symbolische Links usw. Ich möchte den Besitz auf einen angemessenen Wert ändern

find . -type f -exec chown username {} \;
find . -type d -exec chown username {} \;
find . -type d -exec chgrp usergroup {} \;
find . -type f -exec chgrp usergroup {} \;

(Verzeih mir, wenn das Ende rückwärts ist ... Ich habe es vor einer Stunde angeschaut und bin mir immer noch nicht sicher)

Aber ich habe Angst, es wegen Reittieren, symbolischen Links usw. zu betreiben. Ich habe den ultimativen Fehler von chmod gemacht. * Und hatte es schon einmal auf mich zurückgeworfen. Ich weiß, dass -xdev auf das Überqueren von Partitionen verzichten wird, aber ich bin nicht sicher, was mit den Dateien in Verzeichnissen geschehen wird, die symbolische Links sind.

Wie beherrscht man dieses Biest, das wichtige Dateien töten kann?

Aktualisieren Sie das Beschneiden der besten Vorschläge unten und fassen Sie zusammen:

  1. Lassen Sie ein Übungsverzeichnis mit anderen Übungsverzeichnissen verknüpfen und bereitstellen.
  2. Verwenden Sie xargs anstelle des nicht intuitiven Befehls exec.
  3. Verwenden Sie -exec echo {} für Vernunft und Sicherheit
  4. Semikolon ist etwas Besonderes und Sie entkommen ihm, daher steht der Fluchtcharakter an erster Stelle
  5. Mit dem Befehl -or können Sie Auswahlkriterien kombinieren.

Ich bin ein wenig verwirrt über den print0, aber xargs war schon immer ein bisschen auf die nicht leicht zu verstehende Übung auf den ersten Blick, die ich zu vermeiden versuche.


1
Ich kann mich auch nicht daran erinnern, also pfeife ich es einfach in xargs.
Resonator

2
Wenn Sie mit dem Erstellen des richtigen Befehls zufrieden sind, sollten Sie ihn mit + anstelle von \ ausführen. Mit + wird es schneller ausgeführt, da der Befehl exec viel seltener aufgerufen wird.
wzzrd

wzzrd, toller Tipp zur Verwendung von + anstelle von \;
Daniel Lawson

Antworten:


19

Nun, was die -execSyntax angeht, könnte man viele Leute mögen, aufgeben und verwenden xargs:

find . -type f | xargs chown username

(oder die Dateien-mit-Leerzeichen-und-anderem-Unsinn-in-ihnen-sicheren Version)

find . -type f -print0 | xargs -0 chown username

Um sich an das Richtige zu erinnern, das mit dem Semikolon zu tun hat, müssen Sie in Ihren Kopf bohren, dass Sie ein Semikolon verwenden, um den ausgeführten Befehl zu beenden-exec , und Sie müssen dem Semikolon entkommen, weil es etwas Besonderes hat Bedeutung zu bash. Deshalb ist es Backslash-Semikolon. Sie scheinen den {}Ersatzteil in Ordnung zu haben.

Wenn Sie etwas Großes und Gefährliches ausführen möchten, von dem Sie sprechen, gehen Sie zunächst wie folgt vor:

find . -type f -exec echo chown username {} \;

und überprüfen Sie die Ergebnisse. Dies ist im Grunde ein "Trockenlauf", bei dem Sie die Befehle sehen, die ausgeführt werden würden, wenn Sie es zulassen. Auf jeden Fall eine gute Praxis. Hilft nicht bei dem .*Problem, aber Sie wissen, dass Sie das jetzt nicht tun sollen. :) :)


1
+! für den 'Echo'-Übungslauf. Ich benutze dies immer für eine große Veränderung
Steve Folly

3

Ich bin überrascht, dass noch niemand die folgende Option erwähnt hat:

find . -type f -ok chown username {} \;

Diese Syntax bestätigt den Befehl, bevor er ausgeführt wird. Dies funktioniert am besten, wenn Sie davon ausgehen, dass es sich bei Ihrer Übereinstimmung um eine relativ kleine Anzahl von Dateien handelt, da für jede Datei eine Aufforderung angezeigt wird.

Einige Antworten erwähnen xargs, aber mit GNU finden, dass auch das unnötig ist:

find . -type f -exec chown username {} \+

Beachten Sie, dass das + normalerweise nicht maskiert werden muss, aber es ist gut, sich daran zu gewöhnen, dies trotzdem zu tun.


Können Sie die Art des Pluszeichens erklären ... was genau macht es? Verarbeitet die Shell es oder den Befehl? Ich denke, ich werde den Quellcode für gnu-find herunterladen, da dies ein interessantes Thema ist.
Ojblass

find verarbeitet es. Lesen Sie man find, um mehr über diese Option zu erfahren.
Kamil Kisiel

3

Dafür ist man da: Es kann schwierig sein, sich an Dinge zu erinnern, deshalb enthält der Befehl * nix Manpages. Sie können einfach immer im Abschnitt ACTION der Manpage nach einer Erinnerung an die Syntax suchen : man find. Obwohl Manpages nicht besonders freundlich erscheinen, sind sie sehr praktisch, wenn Sie sie einmal gut gelesen haben.

Erstellen eines Frontends oder Wrappers: Als ich bei GNU find besser werden wollte, habe ich ein GUI-Frontend für find geschrieben , das Suchbefehle mit Python, Glade und Pygtk generiert. Dies ist eine gute Übung, wenn Sie sie wirklich gut kennenlernen möchten.

Haben Sie ein Übungsverzeichnis: Schließlich habe ich immer ein 'Scrap'-Verzeichnis in meinem Home-Verzeichnis, um mit leistungsstarken Befehlen zu spielen, wenn etwas wie' Echo 'es nicht schneidet. Sie können die Shell-Erweiterung verwenden, um schnell eine Reihe von Dateien mit folgenden Elementen zu erstellen:

for i in {1..100}; do touch "$i"; done

Ein seltsames Übungsverzeichnis habe ich nie in Betracht gezogen.
Ojblass

1

Sie können Suchausdrücke auch mit den Operatoren '-und' und '-or' kombinieren. -und ist implizit:

find . -type f -name "plainfile" ...

ist das gleiche wie

find . -type f -and -name "plainfile" ...

Der Operator oder kann Ihre Liste mit 4 Befehlen auf 2 reduzieren:

find . -type d -or -type f ...

Und schließlich kann nicht die Suche, sondern Chown auch die Gruppe setzen. Wenn wir also auch mit Leerzeichen in Namen umgehen, erhalten wir:

find . -type d -or -type f -exec chown username:usergroup '{}' \;

Was finden Sie mit dem -oder Geschäft. [Sic]
Ojblass

@ojblass: find kombiniert Ausdrücke mit 'und' oder 'oder'. Wenn weder '-and' noch '-or' angegeben sind, wird '-and' implizit verwendet. Geben Sie also 'find -type d -type f' ein, da nichts ein Verzeichnis und eine Datei ist.
Steve Folly

0

Beim Schließen denke ich nur an die Verwendung; wie bei vielen Programmiersprachen und dann entkommen. Denken Sie daran, dass es entkommen muss und es Ihnen ziemlich leicht fällt.


0

Abhängig von der Version von find, die Sie verwenden, gibt es verschiedene Optionen, die Ihnen helfen können. Der GNU-Fund ist wahrscheinlich der mächtigste und dies kann Ihnen bei Ihrer zweiten (impliziten) Frage helfen

Zum Beispiel - das Standardverhalten besteht nicht darin, symbolische Links zu dereferenzieren, aber Sie können dies überschreiben. und die Option -mount stoppt das Auffinden von Mount-Punkten

Schauen Sie in Ihren lokalen Manpages nach


0

Einige würden argumentieren, dass die Option xargs schneller ist als die Option -exec, da der Befehl nicht für jede Datei einmal ausgeführt wird, aber ich würde mir darüber keine Sorgen machen, außer für massive Jobs, die nicht trivial viel Zeit in Anspruch nehmen.

Persönlich laufe ich normalerweise nur find ohne exec

find /path/to/dir -name whatever

Stellen Sie sicher, dass die Ausgabe korrekt aussieht, und führen Sie dann meinen Befehl für diese Liste aus.

chown user:group `find /path/to/dir -name whatever`

Perfektes Beispiel dafür, wie man Dinge nicht tut. Dateinamen mit Leerzeichen.
Ian Kelling

Ja, das ist ein potenzielles Problem, das ich vielleicht hätte anerkennen müssen. Mein Punkt war jedoch, die Find-Ausgabe zu lesen, bevor etwas ausgeführt wurde, wo Sie Leerzeichen oder anderen Wahnsinn von Dateinamen erkennen würden.
Theotherreceive

0

Für einige Muscheln (nicht Bash) entkommen Sie {} für ein korrektes Verhalten.

\{\} or '{}'

find manual ist gut für das Beherrschen von find.


Nein, tust du nicht; find läuft gut mit dem {} wie sie sind. Sie sind Teil des Befehls find: Sie sind ein Token, das durch das Ergebnis des Befehls find ersetzt wird. Sie bedeuten nur etwas in Bash, wenn Funktionen definiert oder Variablen aufgerufen werden. Sie können sie also einfach wie in der ursprünglichen Frage verwenden.
wzzrd

Es ist von der Manpage. Ich habe aktualisiert, um zu sagen, dass es nicht für Bash gilt.
Ian Kelling

0

Bevor Sie so etwas tun, stellen Sie sicher, dass sich das Verzeichnis, für das Sie diesen Befehl ausführen, nicht im selben Dateisystem befindet wie / usr oder / etc. (Andernfalls, wenn ich einen festen Link zu / etc / passwd oder / bin / sh in meinem Home-Verzeichnis habe, haben Sie mir gerade das Eigentum an diesen gegeben und als Nebeneffekt besitze ich jetzt die Maschine).

Wenn Sie ein Verzeichnis durchsuchen und alle Dateien / Verzeichnisse durchsuchen möchten, ist dies ganz einfach

chown -Rh Benutzer: Benutzergruppe Benutzer /

werde es tun. Stellen Sie sicher, dass Sie das -h oder chown verwenden, um symbolischen Links zu folgen.


Ich denke nicht, dass dies plattformübergreifend ist. Scheitert auch mit 247 KB Dateien, wie meine Übungsumgebung zeigt. Ich bin mir nicht sicher warum.
Ojblass

Ich denke, Sie haben mehr einen Fehler gefunden als ein plattformübergreifendes Problem. Welche Version und wie ist der Exit-Status, wenn sie fehlschlägt? Soweit ich das beurteilen kann, entstand es zuerst in frühen bsd-Versionen; Es ist definitiv in Sunos 5.3 und Ultrix und Irix. Wie viele verarbeitet es, bevor es fehlschlägt?
Chris

Sie haben Recht, es funktioniert unter AIX 5.3, AIX 5.2, aber nicht unter AIX 4.3, NCR, HP 11, HP 10.20 oder meinen DSL-Distributionen. In allen Fällen scheint es bei oder nahe 60.000 Dateien fehlzuschlagen.
Ojblass
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.