Je souhaite rechercher les fichiers qui se terminent par _peaks.bed
, mais excluent les fichiers des dossiers tmp
et scripts
.
Ma commande est comme ceci:
find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)
Mais ça n'a pas marché. Les fichiers dans tmp
et le script
dossier seront toujours affichés.
Quelqu'un a-t-il des idées à ce sujet?
_peaks.bed
.find
, mais comme la question est étiquetée Linux, ce n'est pas un problème. Bonne réponse..
à votre invite de recherche initiale, vous devez l'utiliser dans chaque chemin que vous excluez. La correspondance de chemin est assez stricte, elle ne fait pas de recherche floue. Donc, si vous utilisez, celafind / -type f -name *.bed" ! -path "./tmp/"
ne fonctionnera pas. vous devez le! -path "/tmp"
rendre heureux.$ ! -path "./directory/*"
-prune
plutôt que de vérifier chaque fichier de l'arborescence." Si vos répertoires exclus fonctionnent très profondément ou contiennent des tonnes de fichiers et que vous vous souciez des performances, utilisez-prune
plutôt l' option.Voici une façon de le faire ...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
la source
find
, plutôt qu'avec uniquement GNUfind
. Cependant, la question est étiquetée Linux donc ce n'est pas critique.Utilisation
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
ou
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
ou
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
L'ordre est important. Il évalue de gauche à droite. Commencez toujours par l'exclusion de chemin.
Explication
N'utilisez pas
-not
(ou!
) pour exclure tout le répertoire. Utilisez-prune
. Comme expliqué dans le manuel:et dans le manuel de recherche de GNU:
En effet, si vous utilisez
-not -path "./pathname"
, find évaluera l'expression pour chaque nœud sous"./pathname"
.Les expressions find ne sont que des évaluations de conditions.
\( \)
- fonctionnement des groupes (vous pouvez utiliser-path "./tmp" -prune -o -path "./scripts" -prune -o
, mais c'est plus verbeux).-path "./script" -prune
- si-path
retourne true et est un répertoire, renvoie true pour ce répertoire et ne le fait pas descend dedans.-path "./script" ! -prune
- il évalue comme(-path "./script") AND (! -prune)
. Cela change le "toujours vrai" du pruneau en toujours faux. Cela évite d'imprimer"./script"
en correspondance.-path "./script" -prune -false
- puisque-prune
renvoie toujours vrai, vous pouvez le suivre avec-false
pour faire la même chose que!
.-o
- Opérateur OR. Si aucun opérateur n'est spécifié entre deux expressions, la valeur par défaut est l'opérateur AND.Par conséquent,
\( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
est étendu à:[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
L'impression est ici importante car sans elle est étendue à:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
est ajouté par find - c'est pourquoi la plupart du temps, vous n'avez pas besoin de l'ajouter dans votre expression. Et puisque-prune
renvoie true, il affichera "./script" et "./tmp".Ce n'est pas nécessaire dans les autres car nous avons basculé
-prune
pour toujours retourner faux.Astuce: vous pouvez utiliser
find -D opt expr 2>&1 1>/dev/null
pour voir comment il est optimisé et développé,find -D search expr 2>&1 1>/dev/null
pour voir quel chemin est vérifié.la source
Essayez quelque chose comme
find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)
et ne soyez pas trop surpris si je me trompe un peu. Si l'objectif est un exécutable (au lieu d'imprimer), remplacez-le simplement.
la source
pour moi, cette solution n'a pas fonctionné sur un exécutable de commande avec find, je ne sais pas vraiment pourquoi, donc ma solution est
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
Explication: identique à sampson-chen one avec les ajouts de
-prune - ignore le chemin de procédure de ...
-o - Ensuite, si aucune correspondance ne correspond, imprimez les résultats, (élaguez les répertoires et imprimez les résultats restants)
18:12 $ mkdir a b c d e 18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b 18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \; gzip: . is a directory -- ignored gzip: ./a is a directory -- ignored gzip: ./b is a directory -- ignored gzip: ./c is a directory -- ignored ./c/3: 0.0% -- replaced with ./c/3.gz gzip: ./d is a directory -- ignored ./d/4: 0.0% -- replaced with ./d/4.gz gzip: ./e is a directory -- ignored ./e/5: 0.0% -- replaced with ./e/5.gz ./e/a: 0.0% -- replaced with ./e/a.gz ./e/b: 0.0% -- replaced with ./e/b.gz
la source
find . -path ./scripts -prune -name '*_peaks.bed' -type f
. Je ne sais pas comment exclure plusieurs répertoires. Cela répertorie également le répertoire exclu de niveau supérieur même s'iltype
est spécifié. Exclure via Grep semble plus simple à moins que vous ne souhaitiez utiliser prune pour accélérer l'opération de recherche.Vous pouvez essayer ci-dessous:
find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'
la source