Je ne comprends pas très bien l'exemple donné par le man find
, peut-on me donner des exemples et des explications? Puis-je combiner l'expression régulière en elle?
La question plus détaillée est la suivante:
Ecrivez un script Shell, changeall
, qui a une interface comme changeall [-r|-R] "string1" "string2"
. Il trouvera tous les fichiers avec un suffixe de .h
, .C
, .cc
, ou .cpp
et changer toutes les occurrences de string1
à string2
. -r
est une option permettant de rester dans le répertoire actuel uniquement ou avec les sous-répertoires.
REMARQUE:
ls
n'est PAS autorisé, nous ne pourrions utiliser que find
et sed
.find -depth
_ mais ce n'était PAS supporté. C'est pourquoi je me demandais si -Prune
pourrait aider, mais n'a pas compris l'exemple de man find
.EDIT2: Je faisais un devoir, je n’ai pas posé la question avec beaucoup de détails parce que j’aimerais le finir moi-même. Puisque je l’ai déjà fait et que je le remets, je peux maintenant poser toute la question. De plus, j'ai réussi à terminer la mission sans utiliser -Prune
, mais aimerait l’apprendre quand même.
Ce que j'avais trouvé déroutant à propos de -Prune
, C'est que c'est une action (comme -print
), Pas un test (comme -name
). Il modifie la liste des tâches 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 que -o
(OU logique) immédiatement après -Prune
, Car cette première partie du test (y compris -Prune
) Retournera false pour ce que vous voulez réellement (par exemple: ce que vous ne voulez pas Taillez dehors).
Voici un exemple:
find . -name .snapshot -Prune -o -name '*.foo' -print
Cela trouvera les fichiers "* .foo" qui ne se trouvent pas dans les répertoires ".snapshot". Dans cet exemple, -name .snapshot
Constitue le [conditions to Prune]
, Et -name '*.foo' -print
Est [your usual conditions]
Et [actions to perform]
.
Notes importantes:
Si vous souhaitez simplement imprimer les résultats, vous serez peut-être habitué à ne pas utiliser l'action -print
. En général vous ne voulez pas lorsque vous utilisez -Prune
.
Le comportement par défaut de find consiste à "et" l'expression ( entière 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
est équivalent à é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
Si votre "condition habituelle" correspond à des fichiers qui correspondent également à votre condition d'élagage, ces fichiers ne seront pas inclus dans la sortie. Pour résoudre ce problème, ajoutez un prédicat -type d
À votre condition Prune.
Par exemple, supposons que nous voulions supprimer tous les répertoires commençant par .git
(Ceci est certes quelque peu artificiel - normalement, il vous suffit de supprimer le nom exactement .git
), Mais à part cela, souhaitait voir tous les fichiers, y compris les fichiers tels que .gitignore
. Vous pourriez essayer ceci:
find . -name '.git*' -Prune -o -type f -print # DON'T DO THIS
Ceci n'inclurait pas .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 pour find
contient une explication plus détaillée que sa page de manuel (true) pour la plupart des GNU).
Attention, -Prune n'empêche pas de descendre dans le répertoire any comme certains l'ont dit. Il empêche la descente dans les répertoires correspondant au test auquel il est appliqué. Peut-être que quelques exemples aideront (voir le bas pour un exemple de regex). Désolé pour être 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, notre manière de faire les choses sous Linux et notre façon de penser sont de gauche à droite.
Donc, vous écrivez ce que vous recherchez en premier:
find / -name "*.php"
Ensuite, vous appuyez probablement sur Entrée et vous réalisez que vous obtenez trop de fichiers de répertoires que vous ne souhaitez pas. Excluons/media pour éviter de rechercher vos lecteurs montés.
Vous devriez maintenant juste ajouter 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
............... | <--- Include ---> | .................... | <- -------- 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 représentant pour créer des réponses) ...
En combinant -Prune
avec d’autres expressions, il existe une différence subtile de comportement en fonction des autres expressions utilisées.
L'exemple de @Laurence Gonsalves trouvera les fichiers "* .foo" qui ne se trouvent pas dans les répertoires ".snapshot": -
find . -name .snapshot -Prune -o -name '*.foo' -print
Cependant, ce raccourci légèrement différent listera également, peut-être par inadvertance, le .snapshot
répertoire (et tous les répertoires .snapshot imbriqués): -
find . -name .snapshot -Prune -o -name '*.foo'
La raison en est (selon la page de manuel sur mon système): -
Si l'expression donnée ne contient aucune des primitives -exec, -ls, -ok ou -print, l'expression donnée est effectivement remplacée par:
(given_expression) -print
Autrement dit, le deuxième exemple équivaut à entrer le texte suivant, ce qui modifie le regroupement de termes: -
find . \( -name .snapshot -Prune -o -name '*.foo' \) -print
Cela a au moins été vu sous Solaris 5.10. Ayant utilisé diverses saveurs de * nix pendant environ 10 ans, je n’ai que récemment cherché la raison pour laquelle cela se produit.
Prune est une option ne pas recurse à n’importe quel commutateur d’annuaire.
De la page de manuel
Si -pth n'est pas donné, c'est vrai; si le fichier est un répertoire, n'y descendez pas. Si -depth est donné, faux; aucun effet.
Fondamentalement, il ne sera pas inséré dans les sous-répertoires.
Prenez cet exemple:
Vous avez les répertoires suivants
Si vous exécutez find -name test2
:
Il retournera les deux répertoires
Si vous exécutez find -name test2 -Prune
:
Il retournera seulement/home/test2 car il ne descendra pas dans/home/test2 pour trouver/home/test2/test2
Je ne suis pas un expert en la matière (et cette page a été très utile avec http://mywiki.wooledge.org/UsingFind )
Je viens de remarquer que -path
Est pour un chemin qui correspond totalement à la chaîne/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 actuel ( en tant que résultat 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 find si vous obtenez des correspondances avec elle ( de l'autre côté du ou '-o
') il n'y a probablement pas de taille! J'ignorais naïvement cela et cela m'a mis à utiliser -path quand c'est génial quand vous ne voulez pas tailler tout le sous-répertoire avec le même nom de base: D
Afficher tout, y compris dir, mais pas son contenu long et ennuyeux:
find . -print -name dir -Prune
Si vous lisez toutes les bonnes réponses ici, je pense maintenant que les suivantes donnent 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 toujours tout dans dir1. Je suppose que la vraie question est de savoir comment -or
Supprimer les résultats non désirés sans les rechercher.
Donc, je suppose que Prune signifie ne pas faire de matches passés corrects, mais le marquer comme terminé ...
http://www.gnu.org/software/findutils/manual/html_mono/find.html "Cela n'est toutefois pas dû à l'effet de l'action '-Prune' (qui empêche uniquement la descente ultérieure , cela ne garantit pas que 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 est inutile d’évaluer le côté droit ("-print") pour ce fichier particulier. "
find
construit une liste de fichiers. Il applique le prédicat que vous avez fourni à chacun et renvoie ceux qui passent.
Cette idée que -Prune
signifie que exclure des résultats était vraiment déroutant pour moi. Vous pouvez exclure un fichier sans Prune:
find -name 'bad_guy' -o -name 'good_guy' -print // good_guy
Tout -Prune
ne modifie pas le comportement de la recherche. Si la correspondance en cours est un répertoire, il est indiqué "hey find
, le fichier que vous venez de faire correspondre, n'y descendez pas". Il supprime simplement cette arborescence (mais pas le fichier lui-même) de la liste des fichiers à rechercher.
Il devrait être nommé -dont-descend
.