Comment exclure un répertoire en trouver. commande
j'essaie d'exécuter une commande find
pour tous les fichiers JavaScript, mais comment exclure un répertoire spécifique?
voici le code find
que nous utilisons.
for file in $(find . -name '*.js')
do
java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
30 réponses
utilisez le commutateur prune, par exemple si vous voulez exclure le répertoire misc
ajoutez simplement un -path ./misc -prune -o
à votre commande de recherche:
find . -path ./misc -prune -o -name '*.txt' -print
Voici un exemple avec plusieurs répertoires:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
ici nous excluons dir1, dir2 et dir3, puisque dans find
expressions c'est une action, qui agit sur les critères -path dir1 -o -path dir2 -o -path dir3
(si dir1 ou dir2 ou dir3), et avec type -d
. Une autre action est -o print
, juste imprimer.
si -prune
ne fonctionne pas pour vous, ce sera:
find -name "*.js" -not -path "./directory/*"
je trouve que les éléments suivants sont plus faciles à raisonner que d'autres solutions proposées:
find build -not \( -path build/external -prune \) -name \*.js
cela vient d'un cas d'utilisation réelle, où j'ai dû appeler Yui-compresseur sur certains fichiers générés par wintersmith, mais en laissant de côté d'autres fichiers qui doivent être envoyés tels quels.
à l'Intérieur \(
et \)
est une expression qui correspond à exactement build/external
(il not match si vous avez fait find ./build
, par exemple -- vous devez le changer en ./build/external
dans ce cas), et will, on success, éviter de traverser quoi que ce soit en dessous de . Elle est alors groupée en une seule expression avec la parenthèse échappée, et préfixée avec -not
qui fera que find
sautera tout ce qui a été apparié par cette expression.
on pourrait se demander si l'ajout de -not
ne fera pas tous les autres fichiers caché par -prune
réapparaît, et la réponse est non. La façon dont -prune
fonctionne est que tout ce qui, une fois qu'il est atteint, les fichiers au-dessous de ce répertoire sont de façon permanente ignorés.
qui est également facile à étendre pour ajouter des exclusions supplémentaires. Par exemple:
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
il y a clairement une certaine confusion ici quant à la syntaxe préférée pour sauter un répertoire.
GNU Avis
To ignore a directory and the files under it, use -prune
De la GNU trouver l'homme page
raisonnement
-prune
empêche find
de descendre dans un répertoire. Juste en précisant -not -path
descendra toujours dans le a sauté , mais -not -path
sera faux chaque fois que find
teste chaque fichier.
Problèmes avec les -prune
-prune
fait ce qu'il veut faire, mais il reste certaines choses que vous devez prendre soin lors de l'utilisation.
-
find
imprime le répertoire pruned.- vrai c'est un comportement intentionnel, il ne descend tout simplement pas en elle. Pour éviter d'imprimer le répertoire, utilisez une syntaxe qui l'omet logiquement.
-
-prune
fonctionne uniquement avec-print
et aucune autre action.- PAS VRAI .
-prune
fonctionne avec toute action à l'exception de-delete
. pourquoi ça ne marche pas avec delete? pour-delete
pour travailler, trouver doit parcourir le répertoire dans L'ordre DFS, puisque-delete
supprimera d'abord les feuilles, puis les parents des feuilles, etc... Mais pour spécifier-prune
pour avoir du sens,find
doit frapper un répertoire et arrêter de le descendre, ce qui n'a clairement aucun sens avec-depth
ou-delete
sur.
- PAS VRAI .
Performance
j'ai mis en place un test simple des trois réponses complémentaires sur cette question (remplacé -print
par -exec bash -c 'echo " 1519220920 "' {} \;
pour montrer un autre exemple d'action). Les résultats sont en dessous de
----------------------------------------------
# of files/dirs in level one directories
.performance_test/prune_me 702702
.performance_test/other 2
----------------------------------------------
> find ".performance_test" -path ".performance_test/prune_me" -prune -o -exec bash -c 'echo ""151910920""' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 23513814
> find ".performance_test" -not \( -path ".performance_test/prune_me" -prune \) -exec bash -c 'echo ""151910920""' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 10670141
> find ".performance_test" -not -path ".performance_test/prune_me*" -exec bash -c 'echo ""151910920""' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 864843145
Conclusion
les Deux f10bit de la syntaxe et Daniel C. Sobral de la syntaxe a pris 10-25ms pour courir sur la moyenne. la syntaxe de GetFree , qui n'utilise pas -prune
, a pris 865ms. Donc, oui c'est un exemple assez extrême, mais si vous vous souciez du temps d'exécution et que vous faites quelque chose d'intensif à distance vous devriez utiliser -prune
.
Note la syntaxe de Daniel C. Sobral a réalisé le meilleur des deux syntaxes -prune
; mais, je soupçonne fortement que cela est le résultat d'une certaine mise en cache comme commutation de l'ordre dans la version non-prune a toujours été la plus lente.
Script De Test
#!/bin/bash
dir='.performance_test'
setup() {
mkdir "$dir" || exit 1
mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
"$dir/other"
find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
touch "$dir/other/foo"
}
cleanup() {
rm -rf "$dir"
}
stats() {
for file in "$dir"/*; do
if [[ -d "$file" ]]; then
count=$(find "$file" | wc -l)
printf "%-30s %-10s\n" "$file" "$count"
fi
done
}
name1() {
find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo ""151920920""' {} \;
}
name2() {
find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo ""151920920""' {} \;
}
name3() {
find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo ""151920920""' {} \;
}
printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"
printf "\nRunning performance test...\n\n"
echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"$0\"\' {} \\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf " [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"
echo \> find \""$dir"\" -not \\( -path \""$dir/prune_me"\" -prune \\) -exec bash -c \'echo \"$0\"\' {} \\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf " [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"
echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"$0\"\' {} \\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf " [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"
echo "Cleaning up test files..."
cleanup
une option serait d'exclure tous les résultats qui contiennent le nom du répertoire avec grep. Par exemple:
find . -name '*.js' | grep -v excludeddir
je préfère la notation -not
... c'est plus lisible:
find . -name '*.js' -and -not -path directory
utilisez l'option-prune. Donc, quelque chose comme:
find . -type d -name proc -prune -o -name '*.js'
Le "- type d -name proc -prune " seulement rechercher les répertoires nommés proc à exclure.
L'option '-o' est un 'OU' opérateur.
C'est la seule qui a fonctionné pour moi.
find / -name NameOfFile ! -path '*/Directory/*'
recherche de" NameOfFile "à l'exclusion de"Directory". Mettre l'accent sur les étoiles * .
C'est le format que j'ai utilisé pour exclure certains chemins:
$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"
j'ai utilisé ceci pour trouver tous les fichiers non dedans ".*" chemins:
$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
-prune
fonctionne certainement et est la meilleure réponse parce qu'il empêche de descendre dans le dir que vous voulez exclure. -not -path
qui recherche toujours le dir exclu, il n'affiche tout simplement pas le résultat, ce qui pourrait être un problème si le dir exclu est monté en volume réseau ou si vous n'avez pas de permissions.
la partie délicate est que find
est très particulier sur l'ordre des arguments, donc si vous ne les obtenez pas juste, votre commande peut pas de travail. L'ordre des arguments est généralement comme tel:
find {path} {options} {action}
{path}
: mettez tous les arguments relatifs au chemin en premier, 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
en utilisant -prune
voici un exemple pratique:
# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js
# search for *.js, exclude dir1
find . -path './dir1' -prune -o -type f -iname '*.js' -print
# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print
l'approche-path-prune fonctionne aussi avec des caractères génériques dans le path. Voici une instruction find qui va trouver les répertoires d'un serveur git desservant plusieurs repositioires Git en laissant de côté les répertoires internes git:
find . -type d \
-not \( -path */objects -prune \) \
-not \( -path */branches -prune \) \
-not \( -path */refs -prune \) \
-not \( -path */logs -prune \) \
-not \( -path */.git -prune \) \
-not \( -path */info -prune \) \
-not \( -path */hooks -prune \)
pour une solution de travail (Testée sur Ubuntu 12.04 (Pangolin précis))...
find ! -path "dir1" -iname "*.mp3"
recherchera des fichiers MP3 dans le dossier courant et les sous-dossiers, sauf dans le sous-dossier dir1.
utiliser:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
... pour exclure dir1 et dir2
pour exclure plusieurs répertoires:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)
pour ajouter des répertoires, ajouter -o -path "./dirname/*"
:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)
mais peut-être que vous devriez utiliser une expression régulière , s'il y a beaucoup de répertoires à exclure.
vous pouvez utiliser l'option prune pour y parvenir. Comme par exemple:
find ./ -path ./beta/* -prune -o -iname example.com -print
ou l'option inverse grep "grep-v":
find -iname example.com | grep -v beta
vous pouvez trouver des instructions détaillées et des exemples dans Linux find commande exclure les répertoires de la recherche .
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 . -path ./misc -prune -o -name '*.txt' -print
find va commencer à rechercher des fichiers et des répertoires dans le répertoire courant, d'où le find .
.
l'option -o
représente un et et sépare les deux parties de la commande:
[ -path ./misc -prune ] OR [ -name '*.txt' -print ]
Tout répertoire ou fichier qui est pas ./ misc directory ne passera pas le premier test -path ./misc
. Mais ils seront testés par rapport à la seconde expression. Si leur nom correspond au modèle *.txt
ils sont imprimés, à cause de l'option -print
.
quand find atteint le ./ misc directory, ce répertoire ne satisfait que la première expression. Ainsi ,l'option -prune
sera appliquée. Il indique la commande "find" à not explorer ce répertoire. Tout fichier ou répertoire ./misc ne seront même pas exploré par trouver, ne sera pas testée contre la deuxième partie de l'expression et ne sera pas imprimée.
j'utilisais find
pour fournir une liste de fichiers pour xgettext
, et je voulais omettre un répertoire spécifique et son contenu. J'ai essayé de nombreuses permutations de -path
combiné avec -prune
mais j'ai été incapable d'exclure complètement le répertoire que je voulais supprimer.
bien que j'aie pu ignorer le contenu du répertoire que je voulais ignorer, find
a ensuite retourné le répertoire lui-même comme l'un des résultats, qui a fait planter xgettext
en conséquence (n'accepte pas les répertoires, seulement les fichiers).
ma solution était simplement d'utiliser grep -v
pour sauter le répertoire que je ne voulais pas dans les résultats:
find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext
Qu'il y ait ou non un argument pour find
qui fonctionnera à 100%, Je ne peux pas le dire avec certitude. Utiliser grep
était une solution rapide et facile après quelques maux de tête.
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'
semble fonctionner de la même façon que
find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)
et est plus facile à se rappeler IMO.
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune
cela me convient sur un Mac:
find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune
Il va exclure vendor
et app/cache
dir de recherche nom suffixé par php
.
pour ceux d'entre vous sur les anciennes versions D'UNIX qui ne peuvent pas utiliser - chemin ou - pas
testé sur SunOS 5.10 bash 3.2 et SunOS 5.11 bash 4.4
find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f
how-to-use-prune-option-de-trouver-en-sh est une excellente réponse par Laurence Gonsalves, comment -prune
.
et voici la solution générique:
find /path/to/search \
-type d \
\( -path /path/to/search/exclude_me \
-o \
-name exclude_me_too_anywhere \
\) \
-prune \
-o \
-type f -name '*\.js' -print
pour éviter de taper /path/to/seach/
plusieurs fois, envelopper le find
dans une paire pushd .. popd
.
pushd /path/to/search; \
find . \
-type d \
\( -path ./exclude_me \
-o \
-name exclude_me_too_anywhere \
\) \
-prune \
-o \
-type f -name '*\.js' -print; \
popd
j'ai trouvé le nom des fonctions dans les fichiers c sources exclude *.o et exclure *.swp et exclude (pas de fichier régulier) et exclude la sortie dir avec cette commande:
find . \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
mieux utiliser l'action exec
que la boucle for
:
find . -path "./dirtoexclude" -prune \
-o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;
le exec ... '{}' ... '{}' \;
sera exécuté une fois pour chaque fichier correspondant, en remplaçant les accolades '{}'
par le nom du fichier courant.
notez que les supports sont inclus dans des guillemets simples pour les protéger de l'interprétation en tant que ponctuation de scripts shell * .
Notes
* de la section Exemples de la page de manuel find (GNU findutils) 4.4.2
151970920"
j'ai essayé la commande ci-dessus, mais aucun de ceux qui utilisent "- prune" ne fonctionne pour moi. Finalement, j'ai essayé avec la commande ci-dessous:
find . \( -name "*" \) -prune -a ! -name "directory"
pour ce dont j'avais besoin cela a fonctionné comme ceci, trouver landscape.jpg
dans tous les serveurs à partir de la racine et à l'exclusion de la recherche dans /var
répertoire:
find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
"151930920 la liste de tous les d irectories dans /
grep -v /var
exclut ` / var" de la liste
xargs -I '{}' find '{}' -name landscape.jpg
exécutez n'importe quelle commande, comme find
avec chaque répertoire / résultat de la liste
cela fonctionne parce que find
TESTS les fichiers pour le pattern * foo* ":
find ! -path "dir1" ! -path "dir2" -name "*foo*"
mais il ne pas travail si vous n'utilisez pas un modèle ( find
ne TEST le fichier). Donc find
ne fait aucun usage de son ex-évalué " vrai " & " faux " bool. Exemple pour cas d'utilisation sans travail avec la notation ci-dessus:
find ! -path "dir1" ! -path "dir2" -type f
il n'y a pas de find
test! Donc si vous avez besoin de trouver des fichiers sans aucun motif correspondant utilisez le-prune. En outre, par l'utilisation de prune find
est toujours plus rapide alors qu'il saute vraiment que les répertoires au lieu de correspondre ou mieux ne pas correspondre. Dans ce cas, utilisez quelque chose comme:
find dir -not \( -path "dir1" -prune \) -not \( -path "dir2" -prune \) -type f
ou:
find dir -not \( -path "dir1" -o -path "dir2" -prune \) -type f
concerne
pour FreeBSD utilisateurs:
find . -name '*.js' -not -path '*exclude/this/dir*'
si les répertoires de recherche ont un motif (dans mon cas la plupart du temps); vous pouvez simplement le faire comme ci-dessous:
find ./n* -name "*.tcl"
Dans l'exemple ci-dessus; il recherche dans tous les sous-répertoires commençant par "n".
j'ai trouvé les suggestions sur cette page, et beaucoup d'autres pages ne fonctionnent pas sur mon Mac OS X système. Cependant, j'ai trouvé une variation qui fonctionne pour moi.
la grande idée est de rechercher le Macintosh HD mais d'éviter de traverser tous les volumes externes, qui sont la plupart du temps des sauvegardes de Machine à remonter le temps, des sauvegardes d'image, des partages montés, et des archives, mais sans avoir à les démonter tous, ce qui est souvent peu pratique.
Voici mon travail script, que j'ai nommé "findit".
#!/usr/bin/env bash
# inspired by /q/how-to-exclude-a-directory-in-find-command-63831/"" -print
date
echo ============================
iMac2:~ jas$
les différents chemins ont à faire avec les volumes d'archives externes, machine temporelle, Machines virtuelles, autres serveurs montés, et ainsi de suite. Certains noms de volumes comportent des espaces.
un bon essai est " findit index.php", parce que ce fichier se trouve à de nombreux endroits sur mon système. Avec ce script, il faut environ 10 minutes pour chercher le disque dur principal. Sans ces exclusions, ça prend des heures.