J'essaie de développer une chaîne impliquant un caractère générique et une collection d'extensions spécifiées entre accolades. Rien ne semble fonctionner comme l'illustre l'exemple ci-dessous. la variable firstList
se développe correctement , mais ni l'une ni l'autre secondList
, thirdList
ou se fourthList
développe correctement. J'ai également essayé différentes versions de eval
mais aucune ne fonctionne non plus. Toute aide serait appréciée
#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"
bash
brace-expansion
Leo Simon
la source
la source
eval ls $secondList
fonctionne bien ici ... qu'essayez-vous d'accomplir?eval
obtenir une deuxième série d'extensions.Réponses:
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):
Même s'il existe des fichiers avec d'autres noms:
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).
Nous pouvons désactiver "l'extension de chemin d'accès" pendant un moment:
Le "Pathname Expansion" reçoit deux arguments:
*.ext1
et*.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
.Les valeurs des noms de fichiers ne posent aucun problème d'exécution pour eval:
Mais la valeur de
$list
pourrait être dangereuse. Cependant, la valeur de$list
est définie par le script scriptor. Le script scripteur contrôleeval
: Ne pas utiliser de valeurs définies en externe pour$list
. Essaye ça:Une meilleure alternative.
Une alternative (sans eval) est d' utiliser les "Patterns étendus" Bash :
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.la source
Considérer:
Le problème est que l' expansion d'accolade se fait avant l' expansion variable . Cela signifie que, dans ce qui précède, l'expansion de l'accolade n'est jamais effectuée.
En effet, lorsque bash voit la ligne de commande pour la première fois, il n'y a pas d'accolades. Après
secondList
est agrandi, il est trop tard.Les éléments suivants fonctionneront:
Ici, la ligne de commande a des accolades afin que l' expansion d'accolade puisse être effectuée comme première étape. Après cela, la valeur de
$s
est substituée dans ( expansion variable ), et enfin une expansion de nom de chemin est effectuée.Documentation
man bash
explique l'ordre d'expansion:la source