Wie verhindere ich, dass ein Fund in gefundene Verzeichnisse abfällt?

24

Ich möchte alle Verzeichnisse mit einer bestimmten Zeichenfolge finden, damit ich die darin enthaltenen Dateien erneut suchen kann.

Ich möchte also keine Zeit mit ./my-search-term/dir/my-search-termusw. verschwenden .

Wie kann ich die Rekursion beenden, wenn ich das erste Verzeichnis für meine Suchbegriffe gefunden habe?

Stephen
quelle
3
Haben Sie versucht, mit -prune zu finden? Auf der Manpage: "Wenn es sich bei der Datei um ein Verzeichnis handelt, steigen Sie nicht in dieses Verzeichnis ab. Wenn -depth angegeben ist, false; keine Auswirkung. Da -delete -depth impliziert, können Sie -prune und -delete nicht sinnvoll zusammen verwenden."
Laebshade
1
@laebshade, warum schreibst du das nicht in eine Antwort?
JW013,
@ jw013 Ich hatte zu diesem Zeitpunkt nicht die Zeit, eine genauere Antwort zu geben.
Laebshade

Antworten:

17

Die -pruneAktion macht findkeine Rückholung in das Verzeichnis. Sie können es mit einer anderen Aktion kombinieren wie -exec( in der Größenordnung von -pruneund -execspielt keine Rolle, solange -prunewird so oder so ausgeführt).

find . -name my-search-term -prune -exec find {} … \;

Beachten Sie, dass das Verschachteln findin a find -execetwas problematisch sein kann: Sie können es nicht -execim Inneren verwenden find, da der Terminator vom Äußeren als Terminator angesehen wird find. Sie können das umgehen, indem Sie eine Shell aufrufen, aber keine Anführungszeichen setzen.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +
Gilles 'SO - hör auf böse zu sein'
quelle
Sind die Klammern in Ihrem ersten Befehl erforderlich? -prunegibt true zurück und kann vor das gesetzt werden -exec.
rozcietrzewiacz
@rozcietrzewiacz Nein, sie sind nicht notwendig. -oIch schätze, die Angewohnheit, dort drin zu sein. Und ich denke, -prunevorher zu setzen -execist besser lesbar.
Gilles 'SO- hör auf böse zu sein'
Danke, habe die -pruneOption vorher nicht genutzt.
Haridsv
In meinem Anwendungsfall dieser Befehl: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;gibt den Fehler: find: ./x1: No such file or directory. Die Lösung ist hinzuzufügen-prune am Ende des findBefehls .
Haridsv
(1) Einige Versionen von findexpandieren {}auch dann, wenn es als Teilzeichenfolge eines Arguments zu sehen ist -exec. Eine solche Version von finddrosselt Ihren zweiten Befehl, weil der {}im inneren findBefehl (im Shell-Befehl) durch den Namen des im äußeren gefundenen Verzeichnisses ersetzt wird find. Sie können das beheben, indem Sie sagenfind . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \;  also mit "{"}, welche die Schale in drehen wird {}. … (Fortsetzung)
Scott
6

- nackte Lösungen -

Wenn Sie findden Inhalt des gefundenen Verzeichnisses überspringen, aber weiterhin in anderen Verzeichnissen suchen -prunemöchten , verwenden Sie @laebshade als Vorschlag. Der vollständige Befehl sollte dann so aussehen

 find . -type d -name somename -prune -exec ...

Wenn Sie jedoch die Suche und das Finden des ersten passenden Verzeichnisses findvollständig beenden möchten , suchen Sie nach -quit(seit Version 4.2.3von GNU find). Diese ist etwas kniffliger zu bedienen, da sie findsofort beendet wird - sie -quitmuss also ganz am Ende des Befehls stehen:

find . -type d -name somename -exec ... -quit

Damit dies wie erwartet funktioniert, muss sichergestellt werden, dass die -execRückgabe wahr ist (mit anderen Worten, ein Nullstatus ). Wenn Sie möchten, dass der Exit-Status von -execignoriert wird, damit das -quitimmer funktioniert, brauchen Sie einen kleinen Trick:

find . -type d -name somename \( -exec ... -o -true \) -quit

oder

find . -type d -name somename \( -exec ... -o -quit \)

oder

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- eine Erklärung -

Das Wichtigste an der Funktionsweise findist, dass alle Aktionen ("Tests") als logische Prädikate behandelt werden, die von links nach rechts interpretiert werden. Daher wird die letzte Aktion (zum Beispiel -quit) nur ausgeführt, wenn der gesamte vorherige Teil nicht false zurückgegeben hat . Standardmäßig werden alle Tests mit einem logischen "UND" verknüpft. Die -oOption ändert die Verknüpfung in "ODER".

Ein kniffliges Element von -oist, dass findIhr Befehl "optimiert" werden kann und das -execTeil nicht ausgeführt wird, wenn Sie nur tippen

find . -type d -name somename -exec ... -o -quit

Um dies zu bewältigen, können Sie die findAuswertung aller mit "OR" verknüpften Prädikate erzwingen, indem Sie sie in Klammern setzen.

rozcietrzewiacz
quelle