Comment ouvrir ou listr tous les files dont le nom correspond à deux templates dans Bash

Supposons que j'ai un directory avec des milliers de files; comment pourrais-je ouvrir tous les files dont le nom contient à la fois les strings "rouge" et "vert"?

(En supposant que vous cherchez des noms de files contenant à la fois la string «rouge» et la string «verte»)

Utiliser inutilement bash pour tester les noms de files contre 'rouge' et 'vert' en utilisant l'opérateur de correspondance d'expression régulière =~ :

 for f in * do [[ $f =~ red && $f =~ green ]] && echo Bash: yes: "$f" || echo Bash: no: "$f" done 

Pour utiliser la syntaxe shell standard à l'aide de la case et globs pour find les mêmes files:

 for f in * do case "$f" in *green*red*|*red*green*) echo Case: yes: $f;; *) echo Case: no: $f;; esac done 

Encore plus simple, avec le globing de votre coquille:

 printf "Glob: %s\n" *green*red* *red*green* 

Échantillon:

 $ touch ab aredgreenb agreenredb agreenbred aredbgreen red green redgreen greenred $ for f in * > do > [[ $f =~ red && $f =~ green ]] && echo Bash: yes: "$f" || echo Bash: no: "$f" > done Bash: no: a Bash: yes: agreenbred Bash: yes: agreenredb Bash: yes: aredbgreen Bash: yes: aredgreenb Bash: no: b Bash: no: green Bash: yes: greenred Bash: no: red Bash: yes: redgreen $ for f in * > do > case "$f" in > *green*red*|*red*green*) echo Case: yes: $f;; > *) echo Case: no: $f;; > esac > done Case: no: a Case: yes: agreenbred Case: yes: agreenredb Case: yes: aredbgreen Case: yes: aredgreenb Case: no: b Case: no: green Case: yes: greenred Case: no: red Case: yes: redgreen $ printf "Glob: %s\n" *green*red* *red*green* Glob: agreenbred Glob: agreenredb Glob: greenred Glob: aredbgreen Glob: aredgreenb Glob: redgreen 
 find . -type f -name '*red*' -name '*green*' -exec echo {} + 

Remplacez echo par vi , gvim , less ou la command avec laquelle vous voulez ouvrir les files.

Notez que certains programmes ne peuvent pas gérer plusieurs noms de files sur la command line. Si votre programme choisi est l'un de ceux-ci, remplacez le + à la fin de la ligne par \; . Cela exécutera la command une fois pour chaque nom de file, plutôt qu'une seule fois avec une longue list de noms de files.

xdg-open est une de ces commands. Il détecte le type de file qu'il est demandé d'ouvrir, puis utilise le programme par défaut du système (ou votre programme préféré si vous avez ignoré la valeur par défaut) pour ouvrir le file. S'il ne reconnaît pas le type du file, il vous requestra à quoi l'ouvrir.

L'utiliser avec find comme ceci est un peu utile et un peu ennuyeux en même time. Essayez-le et vous verrez pourquoi (vous verrez beaucoup de windows s'ouvrir, l'une après l'autre … une pour chaque nom de file correspondant).

 find . -type f -name '*red*' -name '*green*' -exec xdg-open {} \; 

BTW, si vous voulez find des files correspondant à *red* OR *green* , vous devez utiliser des parenthèses pour spécifier la priorité pour les opérateurs "et" ( -a ) et "("). BTW, lorsque vous exécutez find avec plusieurs prédicats comme ci-dessus, l'opérateur par défaut est -a , c'est-à-dire que les prédicats sont logiquement ET-ed set.

Les parenthèses ont également une signification spéciale pour le shell, elles doivent donc être antislash-échappées pour qu'elles soient transmises à la command find plutôt qu'interprétées par le shell.

 find . -type f \( -name '*red*' -o -name '*green*' \) -exec echo {} + 

Lisez ceci comme "un file régulier ET (un nom de file correspondant à" * * * * "*" ")

Avec zsh :

 setopt extendedglob # best in ~/.zshrc ls -ld -- *green*~^*red* 

L'opérateur ~ glob est pour sauf ( et non ). ^ est pour pas . Donc, la combinaison est et non pas , et ainsi de suite . IOW, qui correspond aux files avec le nom green , sauf ceux qui ne contiennent pas de red .

Pour inclure également les files cachés, ajoutez le qualificatif (D) glob.

Vous pouvez également utiliser les qualificateurs glob pour faire correspondre les noms de files aux expressions rationnelles, et avec setopt rematchpcre , vous pouvez créer ces expressions rationnelles pour lesquelles vous pouvez utiliser les opérateurs d'anticipation pour:

 re() { setopt localoptions rematchpcre [[ $REPLY =~ $1 ]] } ls -ld -- *(e:'re "(?=.*green).*red"':) 

Ou:

 re() { setopt localoptions rematchpcre [[ $REPLY =~ $RE ]] } RE='(?=.*green).*red'; ls -ld -- *(+re) 

Avec ksh ou bash -O extglob

 ls -ld -- !(!(*green*)|!(*red*)) 

Encore une fois, une double négation: tout sauf les files qui ne contiennent pas de green , ou ne contiennent pas de red .

Tu pourrais aussi faire

 ls -ld -- @(*green*red*|*red*green*) 

Mais ce n'est pas généralisable à n'importe quel model. Par exemple pour les files contenant abc et bcd , vous aurez besoin de @(*abc*bcd*|*abcd*|*bcd*abc*) , pour la correspondance des files ??? et *x* , @(x??|?x?|??x)

Avec ksh93

ksh93 a quelques opérateurs et globbing:

 ls -ld -- @(*green*&*red*) 

Ou en utilisant ses regexps augmentés (introduits avec l'opérateur ~(A:...) glob):

 ls -ld -- ~(A:.*green.*&.*red.*) 

Vous pouvez également utiliser des opérateurs de ksh93 perl-like en ksh93 :

 ls -ld -- ~(P:(?=.*green).*red.*) 

Simple, en supposant que la command open peut gérer plusieurs arguments:

 open *red* *green* 

Edit: désolé je lisais la question comme ouverture (les files avec le nom rouge) et (les files avec le vert dans le nom); mon erreur.

Les utilisations suivantes extglob et évite le double-count dans le cas des files nommés redgreenred :

 $ shopt -s extglob # turn on extended globbing $ printf "extglob: %s\n" @(*green*red*|*red*green*) extglob: agreenbred extglob: agreenredb extglob: aredbgreen extglob: aredgreenb extglob: greenred extglob: redgreen extglob: redgreenred $ shopt -u extglob # turn off extended globbing