J'essaye de lancer un find
commande pour tous les fichiers JavaScript, mais comment exclure un répertoire spécifique?
Voici le find
code que nous utilisons.
for file in $(find . -name '*.js')
do
java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
find ... | while read -r file ...
. En outre, il vaut mieux accepter et voter positivement.for file in $(find .); do echo "$file"; done
. Les noms avec des espaces sont divisés, ce que nous ne voulons pas.Réponses:
Utilisez l'
-prune
interrupteur. Par exemple, si vous souhaitez exclure lemisc
répertoire, ajoutez simplement un-path ./misc -prune -o
à votre commande find:Voici un exemple avec plusieurs répertoires:
Nous excluons ici dir1 , dir2 et rep3 , puisque dans les
find
expressions est une action qui agit sur les critères-path dir1 -o -path dir2 -o -path dir3
(si dir1 ou dir2 ou rep3 ), avec ANDEDtype -d
.Une autre action consiste
-o print
à imprimer.la source
-print
explicitement de (ou toute autre action) après-name
. Dans ce cas, les deux "côtés" de l'-o
impression finissent, alors que si vous utilisez-print
, seul ce côté s'imprime.Because -delete implies -depth, you cannot usefully use -prune and -delete together.
Alors, comment puis-je supprimer avec find si je souhaite exclure des répertoires spécifiques de la suppression?find . -not -path "./.git*"
. Utiliser./dir*
au lieu de./dir/*
supprime le répertoire ainsi que le contenu de la sortie.Si
-prune
cela ne fonctionne pas pour vous, cela:Avertissement: nécessite de parcourir tous les répertoires indésirables.
la source
-prune
n'exclut pas le répertoire lui-même, il exclut son contenu, ce qui signifie que vous allez obtenir une ligne indésirable dans la sortie avec le répertoire exclu..
par*
.find -name "*.js" -not -path "*/omitme/*"
omettrait donc les fichiers d'un répertoire nommé "omitme" à n'importe quel niveau de profondeur.-print
explicitement.Je trouve les éléments suivants plus faciles à raisonner que les autres solutions proposées:
Remarque importante: les chemins que vous tapez après
-path
doivent correspondre exactement à cefind
qui s'imprimerait sans exclusion. Si cette phrase vous embrouille, assurez-vous simplement d'utiliser des chemins complets à travers toute la commande comme ceci:find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
. Voir la note [1] si vous souhaitez une meilleure compréhension.À l'intérieur
\(
et\)
est une expression qui correspondra exactementbuild/external
(voir la note importante ci-dessus) et, en cas de succès, évitera de traverser quoi que ce soit ci-dessous . Ceci est ensuite regroupé en une seule expression avec la parenthèse échappée, et préfixé avec-not
qui ferafind
sauter tout ce qui correspondait à cette expression.On peut se demander si l'ajout
-not
ne fera pas-prune
réapparaître tous les autres fichiers cachés , et la réponse est non. Le chemin-prune
fonctionnement est que tout ce qui, une fois atteint, les fichiers en dessous de ce répertoire sont ignorés de façon permanente.Cela vient d'un cas d'utilisation réel, où j'avais besoin d'appeler yui-compresseur sur certains fichiers générés par wintersmith, mais en laissant de côté les autres fichiers qui doivent être envoyés tels quels.
Remarque [1] : Si vous souhaitez exclure
/tmp/foo/bar
et que vous exécutez find comme ceci "find /tmp \(...
", vous devez le spécifier-path /tmp/foo/bar
. Si d'un autre côté vous lancez find comme ceci,cd /tmp; find . \(...
vous devez spécifier-path ./foo/bar
.la source
find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
-exec rm -rf {} \;
place de-delete
.find
, c'est vraiment évident, mais ça m'a fait trébucher. Si vous êtes à la recherche dans le répertoire courant (en spécifiant.
que le chemin de recherche, ou ne pas spécifier une), vous souhaiterez probablement votre modèle après-path
pour commencer./
, par exemple:find -not \( -path ./.git -prune \) -type f
.find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)
suivie de toutes les conditions qui devraient correspondre à ce que vous recherchez.Il y a clairement une certaine confusion ici quant à la syntaxe préférée pour ignorer un répertoire.
Opinion GNU
Depuis la page de manuel GNU find
Raisonnement
-prune
arrêtefind
de descendre dans un répertoire. La simple spécification-not -path
descendra toujours dans le répertoire ignoré , mais-not -path
sera fausse à chaque fois quefind
chaque fichier sera testé.Problèmes avec
-prune
-prune
fait ce à quoi il est destiné, mais vous devez quand même prendre soin de certaines choses lorsque vous l'utilisez.find
imprime le répertoire élagué.-prune
ne fonctionne qu'avec-print
et aucune autre action.-prune
fonctionne avec n'importe quelle action sauf-delete
. Pourquoi cela ne fonctionne-t-il pas avec la suppression? Pour-delete
travailler, trouver doit parcourir le répertoire dans l'ordre DFS, car-delete
supprimera d'abord les feuilles, puis les parents des feuilles, etc ... Mais pour spécifier-prune
pour avoir du sens, ilfind
faut frapper un répertoire et arrêter de le descendre, ce qui n'a clairement aucun sens avec-depth
ou-delete
sur.Performance
J'ai mis en place un test simple des trois réponses les plus votées sur cette question (remplacé
-print
par-exec bash -c 'echo $0' {} \;
pour montrer un autre exemple d'action). Les résultats sont ci-dessousConclusion
Les deux la syntaxe de f10bit et la syntaxe de Daniel C. Sobral a pris 10-25ms à courir en moyenne. La syntaxe de GetFree , qui ne l'utilise pas
-prune
, a pris 865 ms. Donc, oui, c'est un exemple plutôt extrême, mais si vous vous souciez du temps d'exécution et que vous faites quelque chose d'intensif à distance, vous devez utiliser-prune
.Remarquez que la syntaxe de Daniel C. Sobral a donné le meilleur des deux
-prune
syntaxes; mais, je soupçonne fortement que cela est le résultat d'une mise en cache car le changement de l'ordre dans lequel les deux s'exécutaient a abouti au résultat opposé, tandis que la version non-prune était toujours la plus lente.Script de test
la source
-prune
je peux dire qu'il y a rarement de différence. Gardez à l'esprit que la première commande qui bénéficiera des performances du processeur, le réchauffement du processeur ultérieur> la baisse des performances entraînera un ralentissement mineur (j'ai purgé le cache avant chaque commande en tant que suggestion @ndemou)name1() name2() name3()
script de test @BroSlow ci-dessus pour changer l'ordre d'exécution pour obtenir un visuel sur ce que j'ai dit. Dans la vraie vie, il est cependant imperceptible entre ces deux-là.C'est le seul qui a fonctionné pour moi.
Recherche de "MyFile" à l'exclusion de "Directory". Mettez l'accent sur les étoiles *.
la source
! -path '*/Directory/*'
à votre commande successivement pour ignorer plusieurs répertoiresdocker container
seul travail avecsh -c "find..."
Une option serait d'exclure tous les résultats contenant le nom du répertoire avec grep. Par exemple:
la source
-prune
) - ne fonctionne pas.find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3
mais il peut y avoir une méthode de grep.egrep -v '(dir1|dir2|dir3)'
. Cependant, dans cette étude de cas spécifique, il serait préférable d'exclure les répertoires enfind
soi.Je préfère la
-not
notation ... c'est plus lisible:la source
find
dit: "Pour ignorer un répertoire et les fichiers qu'il contient, utilisez -prune".find . -iname '*' -and -not -path './somePath'
ne l'empêche pas d'entrer dans ledit répertoire.find . -iname '*' -not -path './.git/*'
find . -not -path "*/.git*"
serait ce que vous voulez.Utilisez l'option -prune. Donc, quelque chose comme:
Le '-type d -name proc -prune' ne recherche que les répertoires nommés proc à exclure.
Le «-o» est un opérateur «OU».
la source
-print
à la fin peut améliorer les résultats.find . -type d -name .hg -prune -o -name data
ignoré le contenu des (multiples).hg
répertoires, mais répertorié les.hg
répertoires eux-mêmes. Avec-print
, il ne listait que les répertoires "data" que je cherchais.-prune
fonctionne certainement et est la meilleure réponse car elle empêche de descendre dans le répertoire que vous souhaitez exclure.-not -path
qui recherche toujours le répertoire exclu, il n'imprime tout simplement pas le résultat, ce qui pourrait être un problème si le répertoire exclu est monté sur le volume réseau ou si vous n'avez pas d'autorisations.La partie délicate est qui
find
est très particulière sur l'ordre des arguments, donc si vous ne les obtenez pas correctement, votre commande peut ne pas fonctionner. L'ordre des arguments est généralement le suivant:{path}
: Mettez d'abord tous les arguments liés au chemin, comme. -path './dir1' -prune -o
{options}
: J'ai le plus de succès en mettant-name, -iname, etc
comme dernière option dans ce groupe. Par exemple-type f -iname '*.js'
{action}
: Vous voudrez ajouter-print
lors de l'utilisation-prune
Voici un exemple de travail:
la source
C'est le format que j'ai utilisé pour exclure certains chemins:
J'ai utilisé ceci pour trouver tous les fichiers qui ne se trouvent pas dans les chemins ". *":
la source
L'approche -path -prune fonctionne également avec les caractères génériques dans le chemin. Voici une instruction find qui trouvera les répertoires d'un serveur git desservant plusieurs référentiels git en laissant de côté les répertoires internes git:
la source
Pour exclure plusieurs répertoires:
Pour ajouter des répertoires, ajoutez
-o -path "./dirname/*"
:Mais peut-être devriez-vous utiliser une expression régulière s'il y a beaucoup de répertoires à exclure.
la source
Il y a beaucoup de bonnes réponses, il m'a juste fallu un certain temps pour comprendre à quoi servait chaque élément de la commande et la logique derrière elle.
find commencera à rechercher des fichiers et des répertoires dans le répertoire courant, d'où
find .
.L'
-o
option représente un OU logique et sépare les deux parties de la commande:Tout répertoire ou fichier qui n'est pas le répertoire ./misc ne passera pas le premier test
-path ./misc
. Mais ils seront testés par rapport à la deuxième expression. Si leur nom correspond au motif*.txt
imprimé, à cause de la-print
option.Lorsque find atteint le répertoire ./misc, ce répertoire ne satisfait que la première expression. L'
-prune
option lui sera donc appliquée. Il indique à la commande find de ne pas explorer ce répertoire. Ainsi, aucun fichier ou répertoire dans ./misc ne sera même exploré par find, ne sera pas testé par rapport à la deuxième partie de l'expression et ne sera pas imprimé.la source
Pour une solution de travail (testée sur Ubuntu 12.04 (Precise Pangolin)) ...
recherchera les fichiers MP3 dans le dossier et les sous-dossiers actuels, sauf dans le sous-dossier dir1.
Utilisation:
... pour exclure dir1 ET dir2
la source
une bonne astuce pour éviter d'imprimer les répertoires élagués est d'utiliser
-print
(fonctionne-exec
aussi) après le côté droit de l'-or
après-prune
. Par exemple, ...imprimera le chemin de tous les fichiers sous le répertoire actuel avec l'extension `.j2", en ignorant tous les répertoires cachés. Neat. ne suit pas, ...
car logiquement, il y a un caché
-and
après l'-iname
opérateur et avant l'impression. Cela le lie à la partie droite de la-or
clause en raison de l'ordre booléen des opérations et de l'associativité. Mais les docs disent qu'il y a un caché-print
s'il (ou l'un de ses cousins ...-print0
, etc.) n'est pas spécifié. Alors pourquoi la partie gauche de l'-or
impression n'est-elle pas ? Apparemment (et je n'ai pas compris cela lors de ma première lecture de la page de manuel), c'est vrai s'il n'y en a pas avec uniquement des opérateurs descriptifs ne ferait apparemment rien, donc je suppose que cela a du sens. Comme mentionné ci-dessus, tout cela fonctionne également, donc ce qui suit donne une liste complète pour chaque fichier avec l'extension souhaitée, mais pas la liste du premier niveau de chaque répertoire caché, ...-print
-ou-exec
PARTOUT, auquel cas, -print est logiquement saupoudré de telle sorte que tout soit imprimé. Si même UNprint
opération de style dans une clause, toutes ces logiques cachées disparaissent et vous obtenez seulement ce que vous spécifiez. Franchement, j'aurais peut-être préféré l'inverse, mais unfind
-exec
ls -la
Pour moi (et d'autres sur ce fil), la
find
syntaxe devient assez baroque assez rapidement, donc je jette toujours des parenthèses pour être sûr que je sais ce qui se lie à quoi, donc je crée généralement une macro pour la capacité de frappe et forme toutes ces déclarations comme. ..Il est difficile de se tromper en configurant le monde en deux parties de cette façon. J'espère que cela aide, bien qu'il semble peu probable que quiconque lise la 30 + e réponse et la vote, mais on peut espérer. :-)
la source
Vous pouvez utiliser l'option prune pour y parvenir. Comme par exemple:
Ou l'option grep inverse "grep -v":
Vous pouvez trouver des instructions détaillées et des exemples dans la commande Linux find exclure les répertoires de la recherche .
la source
find . -type f -print -o -path "*/node_modules" -prune
... en utilisant le caractère générique, cela saute "node_modules" à n'importe quel niveau; l'utilisation-print
de la première alternative-type f -print
ne fait qu'imprimer cette partie, donc les répertoires "node_modules" eux-mêmes ne sont pas répertoriés. (il peut aussi être inversé:find . -path "*/node_modules" -prune -o -type f -print
)./node_modules
et en tirer*/node_modules
parti. Pour mon cas, oùnode_modules
n'existe que dans le répertoire dans lequel je lance la recherche (et sous cenode_modules
répertoire), je peux l'utiliserfind . -type f -print -o -path "./node_modules" -prune
car il n'y aura pas denode_modules
répertoire sous aucun autre répertoire.node_modules
sous - répertoire, mais il y avait aussi des sous-répertoires qui avaient leurs propres nœuds_modules ... utilisant./node_modules
uniquement les correspondances du sous-répertoire du répertoirenode_modules
en cours.
et les élaguant; l'utilisation*/node_modules
correspond et élague le répertoire à n'importe quelle profondeur, car le*
as a glob correspond à tout préfixe de chemin principal, tel que./test5/main/node_modules
, non seulement le./
préfixe. Le*
est un caractère générique, mais en tant que glob et non en tant que regex.la source
find ~/Projects -name '*.js' -\! -name 'node_modules' -prune
tourne toujours des fichiers avecnode_modules
sur son cheminfind ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print
. Le nom de ce chemin doit correspondre exactement à ce que la recherche imprimerait si elle devait imprimer le répertoire.semble fonctionner de la même manière que
et il est plus facile de se souvenir de l'OMI.
la source
TLDR: comprenez vos répertoires racine et personnalisez votre recherche à partir de là, en utilisant l'
-path <excluded_path> -prune -o
option. Ne pas inclure de fin/
à la fin du chemin exclu.Exemple:
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
Pour utiliser efficacement le
find
je pense qu'il est impératif d'avoir une bonne compréhension de la structure de répertoire de votre système de fichiers. Sur mon ordinateur personnel, j'ai des disques durs multi-To, avec environ la moitié de ce contenu sauvegardé à l'aidersnapshot
(c'est-à-dirersync
). Bien que la sauvegarde sur un lecteur physiquement indépendant (en double), il est monté sous mon/
répertoire racine système ( )/mnt/Backups/rsnapshot_backups/
:Le
/mnt/Backups/rsnapshot_backups/
répertoire occupe actuellement environ 2,9 To, avec environ 60 millions de fichiers et dossiers; traverser simplement ces contenus prend du temps:Ainsi, chaque fois que je dois rechercher un fichier sur ma
/
partition (racine), je dois gérer (éviter si possible) la traversée de ma partition de sauvegarde.EXEMPLES
Parmi les différentes approches suggérées dans ce fil ( Comment exclure un répertoire dans la commande find. ), Je trouve que les recherches en utilisant la réponse acceptée sont beaucoup plus rapides - avec des mises en garde.
Solution 1
Disons que je veux trouver le fichier système
libname-server-2.a
, mais je ne veux pas parcourir mesrsnapshot
sauvegardes. Pour trouver rapidement un fichier système, utilisez le chemin d'exclusion/mnt
(c'est-à-dire, utilisez/mnt
, pas/mnt/
, ou/mnt/Backups
, ou ...):... trouve ce fichier en quelques secondes, alors que cela prend beaucoup plus de temps (apparaissant comme récurrent dans tous les répertoires "exclus"):
Solution 2
L'autre solution proposée dans ce fil ( SO # 4210042 ) fonctionne également mal:
RÉSUMÉ | CONCLUSIONS
Utilisez l'approche illustrée dans la " Solution 1 "
c'est à dire
notant que chaque fois que vous ajoutez la fin
/
au chemin exclu, lafind
commande entre alors récursivement (tous ces)/mnt/*
répertoires - qui dans mon cas, en raison des/mnt/Backups/rsnapshot_backups/*
sous - répertoires, comprend en outre ~ 2,9 To de fichiers à rechercher! En n'ajoutant pas de fin/
la recherche devrait se terminer presque immédiatement (en quelques secondes).La "Solution 2" (
... -not -path <exclude path> ...
) semble également rechercher récursivement dans les répertoires exclus - ne renvoyant pas les correspondances exclues, mais consommant inutilement ce temps de recherche.Recherche dans ces
rsnapshot
sauvegardes:Pour rechercher un fichier dans l'une de mes
rsnapshot
sauvegardes horaires / quotidiennes / hebdomadaires / mensuelles ):Exclusion d'un répertoire imbriqué:
Ici, je veux exclure un répertoire imbriqué, par exemple
/mnt/Vancouver/projects/ie/claws/data/*
lors de la recherche à partir de/mnt/Vancouver/projects/
:En plus: l' ajout
-print
à la fin de la commande supprime l'impression du répertoire exclu:la source
find
, c'est le nombre d'entrées de répertoire qu'il doit examiner. C'est donc bien pire si vous avez beaucoup, beaucoup de petits fichiers (surtout s'ils sont tous liés par plusieurs!) Que si vous n'avez qu'une poignée de fichiers de plusieurs gigaoctets.sudo ls -R / | wc -l
indique ~ 76,5 millions de fichiers (dont la plupart sont sauvegardés sauf les fichiers système "non config");/mnt/Vancouver/
avecls -R | wc -l
indique ~ 2,35 millions de fichiers;/home/victoria/
contient 0,668 million de fichiers.Vous pouvez également utiliser des expressions régulières pour inclure / exclure certains fichiers / répertoires de votre recherche en utilisant quelque chose comme ceci:
Cela ne vous donnera que tous les fichiers js, vue, css, etc. mais en excluant tous les fichiers dans les dossiers
node_modules
etvendor
.la source
J'utilisais
find
pour fournir une liste de fichiers pourxgettext
, et je voulais omettre un répertoire spécifique et son contenu. J'ai essayé de nombreuses permutations de-path
combiné avec-prune
mais pas pu exclure complètement le répertoire que je voulais quitter.Bien que j'aie pu ignorer le contenu du répertoire que je voulais ignorer, j'ai
find
renvoyé le répertoire lui-même comme l'un des résultats, ce qui a causéxgettext
crash en conséquence (n'accepte pas les répertoires; uniquement les fichiers).Ma solution était de simplement utiliser
grep -v
pour ignorer le répertoire que je ne voulais pas dans les résultats:Qu'il y ait ou non un argument pour
find
que cela fonctionne à 100%, je ne peux pas le dire avec certitude. L'utilisationgrep
était une solution rapide et facile après quelques maux de tête.la source
Aucune des réponses précédentes n'est bonne sur Ubuntu. Essaye ça:
Je l'ai trouvé ici
la source
Cela me convient sur un Mac:
Il exclura
vendor
et dira leapp/cache
nom de recherche avec le suffixephp
.la source
Pour ceux d' entre vous sur les anciennes versions d'UNIX qui ne peuvent pas utiliser -path ou -non
Testé sur SunOS 5.10 bash 3.2 et SunOS 5.11 bash 4.4
la source
how-to-use-prune-option-of-find-in-sh est une excellente réponse de Laurence Gonsalves sur le
-prune
fonctionnement.Et voici la solution générique:
Pour éviter de taper
/path/to/seach/
plusieurs fois, enveloppez-lesfind
dans unepushd .. popd
paire.la source
-path
doit correspondre au nom que find imprimerait s'il devait imprimer le répertoire, par exemplefind . -path ./.git -prune -o -print
, oufind $HOME/foo -path $HOME/foo/.git -prune -o -print
certaines des réponses disent simplement-path somedir
qui est malheureusement pas assez précis pour être utile.Pour ce dont j'avais besoin, cela fonctionnait comme ceci, en trouvant
landscape.jpg
dans tous les serveurs à partir de la racine et en excluant la recherche dans le/var
répertoire:find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d
répertorie tous les d irectories en/
grep -v /var
exclut `/ var 'de la listexargs -I '{}' find '{}' -name landscape.jpg
exécuter n'importe quelle commande, commefind
avec chaque répertoire / résultat de la listela source
/
n'est pas encore exclu. Vous pourriez avoir besoinsed 1d
.Les commandes suivantes fonctionnent:
Si vous rencontrez un problème avec la recherche, utilisez l'
-D tree
option pour afficher les informations d'analyse d'expression.Ou le
-D all
, pour voir toutes les informations d'exécution.la source
J'ai trouvé le nom des fonctions dans les fichiers sources C exclure * .o et exclure * .swp et exclude (fichier non normal) et exclure la sortie dir avec cette commande:
la source
Mieux vaut utiliser l'
exec
action que lafor
boucle:Le
exec ... '{}' ... '{}' \;
sera exécuté une fois pour chaque fichier correspondant, en remplaçant les accolades'{}'
par le nom de fichier actuel.Notez que les accolades sont placées entre guillemets simples pour les protéger de l'interprétation en tant que ponctuation de script shell * .
Remarques
* À partir de la section EXEMPLES de la
find (GNU findutils) 4.4.2
page de manuella source
exec
souvent l' action et la trouve très utile. J'ajoute généralement des guillemets entre{}
dans le cas où il y a des espaces dans les chemins de fichier qui donne"{}"
.{}
fonctionne pour les fichiers avec des espaces dans leurs noms) et un regard dans les pages de manuel, il semble que la citation ne soit nécessaire que pour éviter qu'ils soient mal interprétés comme ponctuation du script shell. Dans ce cas, vous utiliseriez des guillemets simples:'{}'
cp
oumv
ourm
. Je vais le vérifierJ'ai essayé la commande ci-dessus, mais aucun de ceux qui utilisent "-prune" ne fonctionne pour moi. Finalement, j'ai essayé cela avec la commande ci-dessous:
la source