Comment utiliser l'option' - prune ' de 'find' dans sh?

Je ne comprends pas tout à fait l'exemple donné du 'man find', quelqu'un peut-il me donner quelques exemples et des explications? Puis-je combiner l'expression régulière?


la question la plus détaillée est la suivante: écrivez un script shell, changeall, qui a une interface comme" changeall [-r|-R] ""string1 ""string2". Il trouve tous les fichiers avec un suffixe .h. ,C,.cc, or .cpp et changer toutes les occurrences de " string1 "en"string2". -r est l'option pour rester dans le dir actuel seulement ou en incluant des sous-DIR. NOTE: 1) pour le cas non récursif, 'ls' n'est pas autorisé, nous ne pouvons utiliser que 'find' et 'sed'. 2) j'ai essayé 'find-depth' mais il n'était pas supporté. C'est pourquoi je me demandais si '-prune' pouvait aider, mais je n'ai pas compris l'exemple de 'man find'.


Edit 2: je faisais une mission, je n'ai pas posé de question en détail parce que je voudrais la finir moi-même. Puisque je l'ai déjà fait et le donne maintenant, je peux dire toute la question. En outre, j'ai réussi à terminer le travail sans utiliser-prune, mais je voudrais quand même l'apprendre.

178
demandé sur derrdji 2009-09-29 00:47:00

8 réponses

ce que j'ai trouvé confus à propos de -prune c'est que c'est une action (comme -print ), pas un test (comme -name ). Il modifie la liste" à faire", mais retourne toujours 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'à ce que -prune ) retournera false pour la substance que vous voulez réellement (c.-à-d.: la substance que vous ne voulez pas tailler).

voici un exemple:

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

Ce "*.foo " dossiers qui ne sont pas sous ".instantané" des répertoires. Dans cet exemple, -name .snapshot est le "test pour le matériel que vous voulez tailler", et -name '*.foo' -print est le "matériel que vous mettez normalement après le chemin".

Notes importantes :

  1. si tout ce que vous voulez faire est d'imprimer les résultats, vous pourriez être utilisé pour exclure l'action -print . Vous généralement ne pas voulez faire cela en utilisant -prune .

    le comportement par défaut de find est "et" l'expression entière avec l'action -print s'il n'y a pas d'actions autres que -prune (ironiquement) à la fin. Cela signifie que l'écriture de 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 veut dire qu'il imprimera aussi le nom du répertoire que vous élaguez, 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" s'avère correspondre à des fichiers qui correspondent aussi votre condition de prune, ces fichiers seront et non inclus dans la sortie. La façon de corriger ceci est d'ajouter un -type d prédicate à votre condition de prune.

    par exemple, supposons que nous voulions tailler n'importe quel répertoire qui a commencé avec .git (ceci est certes quelque peu artificiel -- normalement vous n'avez besoin de supprimer que la chose nommée exactement .git ), mais autre que cela voulait voir 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
    

    ce serait pas inclure .gitignore dans la sortie. Voici la version corrigée:

    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 de find a une explication plus détaillée que sa page de manuel (comme c'est le cas pour la plupart des utilitaires GNU).

367
répondu Laurence Gonsalves 2014-09-19 16:58:49

attention, prune n'empêche pas de descendre dans Tout répertoire comme certains l'ont dit. Il empêche de descendre dans des répertoires qui correspondent au test auquel il est appliqué. Peut-être que quelques exemples vous aideront (voir l'exemple d'un regex au bas de la page). Désolé pour cet être si longue.

$ 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
26
répondu Dennis Williamson 2009-09-29 00:04:53

normalement, la manière native que nous faisons les choses sous linux et la façon dont nous pensons est de gauche à droite.

Donc vous iriez et écririez ce que vous cherchez en premier:

find / -name "*.php"

alors vous avez probablement frappé enter et vous vous rendez compte que vous obtenez trop de fichiers de les répertoires que vous ne souhaitez pas. Excluons / média pour éviter de chercher dans vos disques montés.

Vous devez maintenant juste ajouter ce qui suit à la commande précédente:

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

donc la commande finale est:

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

...............|<--- Comprendre.|>--- ...................|<---------- Exclure --------->|

je pense que cette structure est beaucoup plus facile et est en corrélation avec la bonne approche

21
répondu AmitP 2013-02-03 17:09:01

ajoute aux conseils donnés dans d'autres réponses (je n'ai pas de Représentant pour créer des réponses)...

en combinant -prune avec d'autres expressions, il y a une différence de comportement subtile en fonction des autres expressions utilisées.

l'exemple de @Laurence Gonsalves trouvera le"*.foo " dossiers qui ne sont pas sous ".snapshot "répertoires: -

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

cependant, cette main courte légèrement différente, peut-être par inadvertance, inscrivez aussi le répertoire .snapshot (et tout répertoire imbriqué).répertoires snapshot): -

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

la raison est (selon la page de manuel sur mon système):-

si l'expression donnée ne contient aucune des primaires-exec, -ls, -ok, ou l'impression à l'expression donnée est effectivement remplacé par:

( given_expression ) -impression

C'est-à-dire, le deuxième exemple est l'équivalent de saisir ce qui suit, modifiant ainsi le groupement de 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.

9
répondu crw 2012-07-04 10:23:51

le Pruneau est un ne pas répéter à tout le répertoire de l'interrupteur.

de la page de manuel

Si la profondeur n'est pas donné, vrai; si le fichier est un répertoire, ne pas descendre en elle. Si-la profondeur est donnée, faux; aucun effet.

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

Prenez cet exemple:

vous avez le répertoires suivants

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

si vous lancez find -name test2 :

il retournera les deux répertoires

si vous lancez find -name test2 -prune :

Il sera de retour que /home/test2 qu'elle ne descend pas dans /home/test2 à find /home/test2/test2

3
répondu AdamW 2009-09-28 21:07:31

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

vient de remarquer -path est pour un chemin qui correspond entièrement à la chaîne de caractères / chemin qui vient juste après find ( . dans ces exemples) où -name correspond à tous les noms de base.

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

bloque le .répertoire git dans votre répertoire courant ( trouver dans . )

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

bloque tout .sous-répertoires git récursivement.

notez que le ./ est extrêmement important!! -path doit correspondre à un chemin ancré à . ou ce qui vient juste après trouver si vous obtenez des allumettes avec hors elle (de l'autre côté de la ou -o ') il n'y a probablement pas être émondé! Je était naïvement ignorant de cela et il m'a mis de l'utilisation-chemin quand il est grand quand vous ne voulez pas tailler tous les sous-répertoires avec le même nom de base :d

2
répondu sabgenton 2013-12-05 09:06:08

montrer tout y compris dir lui-même, mais pas son long contenu ennuyeux:

find . -print -name dir -prune
1
répondu devon 2014-10-24 18:52:22

Si vous lisez toutes les bonnes réponses ici, ma compréhension, c'est que la suite toutes les mêmes résultats:

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 encore tout en dir1. Je suppose que la vraie question Est comment -or sur les résultats indésirables sans réellement les rechercher.

donc prune veut dire ne pas décevoir les matchs passés mais marquer comme fait...

http://www.gnu.org/software/findutils/manual/html_mono/find.html "Cela n'est cependant pas dû à l'effet de l'action ‘-prune’ (qui empêche seulement une descente plus loin, il ne fait pas sûr que nous ignorons cet élément). Au lieu de cela, cet effet est dû à l'utilisation de ‘-o’. Depuis le côté gauche de la condition "ou" a réussi pour ./src/emacs, il n'est pas nécessaire d'évaluer le côté droit (‘-print") à tous pour ce fichier en particulier."

0
répondu sabgenton 2014-09-19 03:43:29