Comment utiliser l’option ‘-prune’ de ‘find’ dans sh?

Je ne comprends pas très bien l’exemple donné par «l’homme trouvé», quelqu’un peut-il me donner des exemples et des explications? Puis-je combiner une expression régulière?


la question plus détaillée est comme ceci: écrire un script shell, changeall, qui a une interface comme “changeall [-r | -R]” ssortingng1 “” ssortingng2 “. Il trouvera tous les fichiers avec un suffixe de .h, .C , .cc ou .cpp et remplacez toutes les occurrences de “ssortingng1” par “ssortingng2”. -r est une option pour restr uniquement dans le répertoire en cours ou en incluant le sous-répertoire. NOTE: 1) pour les cas non récursifs, ‘ls’ , nous ne pouvions utiliser que ‘find’ et ‘sed’ 2) J’ai essayé ‘find -depth’ mais ce n’était PAS supporté C’est pourquoi je me demandais si ‘-prune’ pouvait aider, mais je n’ai pas compris l’exemple de ‘ homme trouver ‘.


EDIT2: Je faisais mon devoir, je ne posais pas de question dans les moindres détails parce que je voudrais le terminer moi-même. Comme je l’ai déjà fait et que je le remets, je peux maintenant énoncer toute la question. De plus, j’ai réussi à terminer l’affectation sans utiliser -prune, mais je voudrais quand même l’apprendre.

Ce que j’ai trouvé déroutant à propos de -prune c’est que c’est une action (comme -print ), pas un test (comme -name ). Cela modifie la liste des tâches à faire, mais renvoie toujours la valeur true .

Le schéma général d’utilisation de -prune est le suivant:

 find [path] [conditions to prune] -prune -o \ [your usual conditions] [actions to perform] 

Vous voulez presque toujours le -o immédiatement après -prune , parce que cette première partie du test (jusqu’à -prune inclus) renverra false pour les choses que vous voulez réellement (par exemple: les choses que vous ne voulez pas éliminer ).

Voici un exemple:

 find . -name .snapshot -prune -o -name '*.foo' -print 

Cela trouvera les fichiers “* .foo” qui ne sont pas sous les répertoires “.snapshot”. Dans cet exemple, -name .snapshot est “teste les éléments que vous voulez élaguer”, et -name '*.foo' -print est le “matériel que vous -name '*.foo' -print normalement après le chemin”.

Notes importantes :

  1. Si tout ce que vous voulez faire, c’est d’imprimer les résultats, vous pourriez être utilisé pour -print action -print . Vous ne voulez généralement pas le faire lorsque vous utilisez -prune .

    Le comportement par défaut de find est de “et” toute l’ expression avec l’action -print s’il n’y a pas d’autres actions que -prune (ironiquement) à la fin. Cela signifie qu’écrire ceci:

     find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS 

    équivaut à écrire ceci:

     find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS 

    ce qui signifie que le nom du répertoire que vous élaguez sera également imprimé, ce qui n’est généralement pas ce que vous voulez. Au lieu de cela, il est préférable de spécifier explicitement l’action -print si c’est ce que vous voulez:

     find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS 
  2. Si votre “condition habituelle” correspond à des fichiers qui correspondent également à votre condition d’élagage, ces fichiers ne seront pas inclus dans la sortie. La solution consiste à append un prédicat de -type d à votre condition d’élagage.

    Par exemple, supposons que nous voulions supprimer tous les répertoires qui ont démarré avec .git (ceci est certes un peu artificiel – normalement il suffit de supprimer tout ce qui est nommé exactement .git ), mais à part cela, tous les fichiers, y compris des fichiers comme .gitignore . Vous pourriez essayer ceci:

     find . -name '.git*' -prune -o -type f -print # DON'T DO THIS 

    Cela n’inclurait pas .gitignore dans la sortie. Voici la version fixe:

     find . -type d -name '.git*' -prune -o -type f -print # DO THIS 

Astuce supplémentaire: si vous utilisez la version GNU de find , la page texinfo pour find a une explication plus détaillée que sa page de manuel (comme c’est le cas pour la plupart des utilitaires GNU).

Méfiez-vous que -prune n’empêche pas de descendre dans un répertoire comme certains l’ont dit. Il empêche de descendre dans les répertoires correspondant au test auquel il est appliqué. Certains exemples aideront peut-être (voir en bas un exemple de regex). Désolé pour ce si long.

 $ find . -printf "%y %p\n" # print the file type the first time FYI d . f ./test d ./dir1 d ./dir1/test f ./dir1/test/file f ./dir1/test/test d ./dir1/scripts f ./dir1/scripts/myscript.pl f ./dir1/scripts/myscript.sh f ./dir1/scripts/myscript.py d ./dir2 d ./dir2/test f ./dir2/test/file f ./dir2/test/myscript.pl f ./dir2/test/myscript.sh $ find . -name test ./test ./dir1/test ./dir1/test/test ./dir2/test $ find . -prune . $ find . -name test -prune ./test ./dir1/test ./dir2/test $ find . -name test -prune -o -print . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2 $ find . -regex ".*/my.*p.$" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test/myscript.pl $ find . -name test -prune -regex ".*/my.*p.$" (no results) $ find . -name test -prune -o -regex ".*/my.*p.$" ./test ./dir1/test ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test $ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py $ find . -not -regex ".*test.*" . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2 

Normalement, la façon native de faire les choses avec Linux et notre manière de penser est de gauche à droite.
Donc, vous allez écrire ce que vous cherchez en premier:

 find / -name "*.php" 

Ensuite, vous appuyez probablement sur Entrée et vous réalisez que vous recevez trop de fichiers des répertoires que vous ne souhaitez pas. Excluons / media pour éviter de chercher dans vos lecteurs montés.
Vous devez maintenant simplement append ce qui suit à la commande précédente:

 -print -o -path '/media' -prune 

la commande finale est donc:

 find / -name "*.php" -print -o -path '/media' -prune 

…………… | < --- Inclure ---> | ……………….. | < - -------- Exclure ---------> |

Je pense que cette structure est beaucoup plus facile et correspond à la bonne approche

Ajout au conseil donné dans d’autres réponses (je n’ai pas de rep pour créer des réponses) …

Lorsque vous -prune avec d’autres expressions, il existe une différence de comportement subtile en fonction des autres expressions utilisées.

L’exemple de @Laurence Gonsalves trouvera les fichiers “* .foo” qui ne figurent pas dans les répertoires “.snapshot”: –

 find . -name .snapshot -prune -o -name '*.foo' -print 

Cependant, ce raccourci légèrement différent affichera peut-être par inadvertance le répertoire .snapshot (et tous les répertoires .snapshot nesteds): –

 find . -name .snapshot -prune -o -name '*.foo' 

La raison en est (selon la page de manuel de mon système): –

Si l’expression donnée ne contient aucune des primaires -exec, -ls, -ok ou -print, l’expression donnée est effectivement remplacée par:

(donne_expression) -print

Autrement dit, le deuxième exemple équivaut à saisir les éléments suivants, modifiant ainsi le regroupement des termes: –

 find . \( -name .snapshot -prune -o -name '*.foo' \) -print 

Cela a au moins été vu sur Solaris 5.10. Ayant utilisé diverses saveurs de * nix pendant environ 10 ans, je n’ai cherché que récemment une raison pour laquelle cela se produit.

Prune est une option qui ne nécessite aucune remise à n’importe quel commutateur de répertoire.

De la page de manuel

Si -depth n’est pas donné, true; Si le fichier est un répertoire, ne le descendez pas. Si -depth est donné, false; aucun effet.

Fondamentalement, il ne sera pas dans les sous-répertoires.

Prenons cet exemple:

Vous avez les répertoires suivants

  • / home / test2
  • / home / test2 / test2

Si vous exécutez find -name test2 :

Il retournera les deux répertoires

Si vous exécutez find -name test2 -prune :

Il ne retournera que / home / test2 car il ne descendra pas dans / home / test2 pour trouver / home / test2 / test2

Je ne suis pas un expert à ce sujet (et cette page était très utile avec http://mywiki.wooledge.org/UsingFind )

Juste remarqué -path est pour un chemin qui correspond entièrement à la chaîne / chemin qui vient juste après find ( . Dans ces exemples) où as -name correspond à tous les noms de base.

 find . -path ./.git -prune -o -name file -print 

bloque le répertoire .git dans votre répertoire actuel ( comme votre recherche dans . )

 find . -name .git -prune -o -name file -print 

bloque tous les sous-répertoires .git de manière récursive.

Notez que le ./ est extrêmement important !! -path doit correspondre à un chemin ancré à . ou tout ce qui vient juste après la recherche si vous obtenez des correspondances avec (de l’autre côté du ou ‘ -o ‘) il n’y a probablement pas d’élagage! J’étais naïvement inconscient de cela et cela m’a mis à utiliser -path quand c’est génial quand vous ne voulez pas éliminer tous les sous-répertoires avec le même nom de base: D

Montre tout, y compris dir lui-même mais pas ses longs contenus ennuyeux:

 find . -print -name dir -prune 

Si vous lisez toutes les bonnes réponses ici, je crois comprendre que les résultats suivants sont les mêmes:

 find . -path ./dir1\* -prune -o -print find . -path ./dir1 -prune -o -print find . -path ./dir1\* -o -print #look no prune at all! 

Mais le dernier prendra beaucoup plus de temps car il cherche toujours tout dans dir1. Je suppose que la vraie question est de savoir comment éliminer les résultats indésirables sans les rechercher réellement.

Donc, je suppose que pruneau signifie ne pas décent des matches passés, mais marquez-le comme fait …

http://www.gnu.org/software/findutils/manual/html_mono/find.html “Ceci n’est cependant pas dû à l’effet de l’action” -prune “(qui n’empêche pas une nouvelle descente, nous ignorons cet élément. Au lieu de cela, cet effet est dû à l’utilisation de “-o”. Puisque le côté gauche de la condition “ou” a réussi pour ./src/emacs, il n’est pas nécessaire d’évaluer le droit côté main (‘-print’) pour ce fichier particulier. ”