Comment empêcher une recherche de descendre dans les répertoires trouvés?

24

Je veux trouver tous les répertoires avec une chaîne spécifique afin que je puisse faire une autre recherche sur les fichiers contenus dans.

Je ne veux donc pas perdre de temps, ./my-search-term/dir/my-search-termetc.

Comment puis-je arrêter la récurrence lorsque j'ai trouvé le premier répertoire my-search-term?

Stephen
la source
3
Avez-vous essayé de trouver avec -prune? À partir de la page de manuel: "si le fichier est un répertoire, ne descendez pas dedans. Si -depth est donné, false; aucun effet. Parce que -delete implique -depth, vous ne pouvez pas utilement utiliser -prune et -delete ensemble."
laebshade
1
@laebshade pourquoi ne mettez-vous pas cela dans une réponse?
jw013
@ jw013 Je n'ai pas eu le temps de fournir une réponse plus approfondie à ce moment-là.
laebshade

Réponses:

17

L' -pruneaction findne fait pas rentrer dans le répertoire. Vous pouvez le combiner avec une autre action telle que -exec(l'ordre de -pruneet -execn'a pas d'importance, tant qu'il -pruneest exécuté de toute façon).

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

Notez que l'imbrication à l' findintérieur d'un find -execpeut être un peu problématique: vous ne pouvez pas l'utiliser -execà l'intérieur find, car le terminateur serait considéré comme un terminateur par l'extérieur find. Vous pouvez contourner cela en invoquant un shell, mais méfiez-vous des citations.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +
Gilles 'SO- arrête d'être méchant'
la source
Les parenthèses de votre première commande sont-elles nécessaires? -prunerenvoie true et peut être placé avant le -exec.
rozcietrzewiacz
@rozcietrzewiacz Non, ils ne sont pas nécessaires. L'habitude d'en avoir un -o, je suppose. Et je suppose que mettre -pruneavant -execest plus lisible.
Gilles 'SO- arrête d'être méchant'
Merci, je n'ai pas utilisé l' -pruneoption avant.
haridsv
Dans mon cas d'utilisation, cette commande: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;donne l'erreur: find: ./x1: No such file or directory. La solution est d'ajouter -pruneen fin de findcommande.
haridsv
(1) Certaines versions de findexpand, {}même si elles apparaissent comme une sous-chaîne d'un argument à -exec. Une telle version de findva étouffer votre deuxième commande, car la commande {}dans la findcommande interne (dans la commande shell) sera remplacée par le nom du répertoire trouvé dans la commande externe find. Vous pouvez résoudre ce problème en disant, find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; c'est-à-dire en utilisant "{"}, dans lequel le shell se transformera {}. … (Suite)
Scott
6

- solutions nues -

Si vous souhaitez findignorer le contenu du répertoire trouvé, mais continuer la recherche dans d'autres répertoires, utilisez -prunecomme suggéré @laebshade. La commande complète devrait alors ressembler à

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

D'un autre côté, si vous voulez arrêterfind complètement la recherche et après avoir trouvé le premier répertoire correspondant, alors ce que vous recherchez est -quit(disponible depuis la version 4.2.3de GNU find). Celui-ci est un peu plus délicat à utiliser, car il fait findsortir immédiatement - il -quitdoit donc être placé à la toute fin de la commande:

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

Pour que cela fonctionne comme prévu, il faut s'assurer que les -execretours sont vrais (en d'autres termes, un statut zéro ). Si vous souhaitez que l'état de sortie de -execsoit ignoré, afin que cela -quitfonctionne toujours, vous avez besoin d'une petite astuce:

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

ou

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

ou

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

- quelques explications -

La chose la plus importante sur le findfonctionnement est que toutes les actions ("tests") sont traitées comme des prédicats logiques interprétés de gauche à droite. Par conséquent, la dernière action (par exemple -quit) ne sera effectuée que si toute la partie précédente n'est pas retournée fausse . Par défaut, tous les tests sont joints avec un "ET" logique, l' -ooption change le joint en "OU".

Un élément délicat -oest que vous findpouvez "optimiser" votre commande et ne pas exécuter la -execpartie si vous tapez juste

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

Pour y faire face, vous pouvez forcer l' findévaluation de tous les prédicats jonés avec "OU", en les mettant entre parenthèses.

rozcietrzewiacz
la source