GNU/Linux >> Tutoriels Linux >  >> Linux

Utilisez la commande find mais excluez les fichiers dans deux répertoires

Voici une façon de procéder...

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"

pour moi, cette solution n'a pas fonctionné sur une commande exec 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 traitement de ...

-o - Ensuite, s'il n'y a pas de correspondance, 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

Voici comment vous pouvez spécifier cela avec find :

find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"

Explication :

  • find . - Lancer la recherche à partir du répertoire de travail actuel (récursivement par défaut)
  • -type f - Spécifiez à find que vous ne voulez que des fichiers dans les résultats
  • -name "*_peaks.bed" - Recherchez les fichiers dont le nom se termine par _peaks.bed
  • ! -path "./tmp/*" - Exclure tous les résultats dont le chemin commence par ./tmp/
  • ! -path "./scripts/*" - Exclure également tous les résultats dont le chemin commence par ./scripts/

Test de la solution :

$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"

./d/4
./c/3
./e/a
./e/b
./e/5

Vous étiez assez proche, le -name l'option ne considère que le nom de base, où -path considère le chemin entier =)


Utiliser

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

Ne pas utiliser -not (ou ! ) pour exclure tout le répertoire. Utilisez -prune .Comme expliqué dans le manuel :

−prune    The primary shall always evaluate as  true;  it
          shall  cause  find  not  to descend the current
          pathname if it is a directory.  If  the  −depth
          primary  is specified, the −prune primary shall
          have no effect.

et dans le manuel GNU find :

-path pattern
              [...]
              To ignore  a  whole
              directory  tree,  use  -prune rather than checking
              every file in the tree.

En effet, si vous utilisez -not -path "./pathname" ,find évaluera l'expression pour chaque nœud sous "./pathname" .

les expressions de recherche ne sont qu'une évaluation de condition.

  • \( \) - opération de groupes (vous pouvez utiliser -path "./tmp" -prune -o -path "./scripts" -prune -o , mais il est plus verbeux).
  • -path "./script" -prune - si -path renvoie vrai et est un répertoire, renvoie vrai pour ce répertoire et ne pas descendez dedans.
  • -path "./script" ! -prune - il est évalué comme (-path "./script") AND (! -prune) . Il ramène le "toujours vrai" de prune à toujours faux. Cela évite d'imprimer "./script" comme un match.
  • -path "./script" -prune -false - depuis -prune renvoie toujours true, vous pouvez le faire suivre de -false faire la même chose que ! .
  • -o - Opérateur OU. 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 importante ici 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 depuis -prune renvoie vrai, il affichera "./script" et "./tmp".

Ce n'est pas nécessaire dans les autres car nous avons basculé -prune pour toujours retourner false.

Astuce :Vous pouvez utiliser find -D opt expr 2>&1 1>/dev/null pour voir comment il est optimisé et étendu,
find -D search expr 2>&1 1>/dev/null pour voir quel chemin est coché.


Linux
  1. Rechercher des fichiers et des répertoires sous Linux avec la commande find

  2. Comment trouver les meilleurs répertoires et fichiers (espace disque) sous Linux

  3. Copier des fichiers et des répertoires sous Linux

  4. Trouver les plus gros fichiers ou répertoires ?

  5. Exclure une liste de répertoires de la commande Unix Find ?

Commande Grep sous Linux (Rechercher du texte dans des fichiers)

Comment utiliser la commande cp pour copier des fichiers et des répertoires

Comment utiliser la commande SCP pour transférer des fichiers

Comment exclure un répertoire lors de la recherche de fichiers sous Linux

Trouvez facilement des fichiers et des répertoires sur Linux

Comment trouver les répertoires ou fichiers les plus gourmands en espace ?