Le shell*
ne se développe que s'il n'est pas cité, toute citation arrête l'expansion par le shell.
En outre, une expansion d'accolade doit être non citée pour être développée par le shell.
Ce travail (permet d'utiliser echo pour voir ce que fait le shell):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Même s'il existe des fichiers avec d'autres noms:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Pourquoi ça marche?
Il est important que nous comprenions pourquoi cela fonctionne. C'est à cause de l'ordre d'expansion. D'abord l '"extension Brace" et plus tard (la dernière) "Expansion Pathname" (alias glob-expansion).
Brace --> Parameter (variable) --> Pathname
Nous pouvons désactiver "l'extension de chemin d'accès" pendant un moment:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
Le "Pathname Expansion" reçoit deux arguments: *.ext1
et *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Le problème est que nous ne pouvons pas utiliser une variable pour l'expansion de l'accolade.
Il a été expliqué à plusieurs reprises pour l' utilisation d'une variable dans une "extension d'accolade"
Pour développer une "extension d'accolade" qui est le résultat d'une "extension variable", vous devez soumettre à nouveau la ligne de commande au shell avec eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Accolade -> Variable -> Glob || -> Accolade -> Variable -> Glob
........ cité ici -> ^^^^^^ || eval ^^^^^^^^^^^^^^^^^^^^^^^^^^
Les valeurs des noms de fichiers ne posent aucun problème d'exécution pour eval:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Mais la valeur de $list
pourrait être dangereuse. Cependant, la valeur de $list
est définie par le script scriptor. Le script scripteur contrôle eval
: Ne pas utiliser de valeurs définies en externe pour $list
. Essaye ça:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Une meilleure alternative.
Une alternative (sans eval) est d' utiliser les "Patterns étendus" Bash :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Remarque: veuillez noter que les deux solutions (eval et patterns) (telles qu'elles sont écrites) sont sans danger pour les noms de fichiers avec des espaces ou de nouvelles lignes. Mais échouera pour un $list
avec des espaces, car $list
n'est pas entre guillemets ou l'évaluation supprime les guillemets.
eval ls $secondList
fonctionne bien ici ... qu'essayez-vous d'accomplir?