Ce problème est très spécifique à bash
, et c'est parce qu'ils ont décidé bash
de séparer l'expansion de l'accolade de l'expansion du nom de fichier (globbing), et de l'exécuter en premier, avant toutes les autres extensions.
Depuis la bash
page de manuel:
L'ordre des expansions est le suivant: expansion de l'accolade; expansion de tilde, expansion de paramètres et de variables, expansion arithmétique et substitution de commandes (effectuées de gauche à droite); division de mots; et expansion du nom de chemin.
Dans votre exemple, bash
ne verra vos accolades qu'après avoir effectué la substitution de commande (la $(echo ...)
), lorsqu'il est trop tard.
Ceci est différent de tous les autres shells, qui effectuent l'expansion de l'accolade juste avant (et certains même dans le cadre de) l'expansion du nom de chemin (globbing). Cela comprend, sans s'y limiter, csh
où les extensions de corset ont été inventées pour la première fois.
$ csh -c 'ls `echo "test{1,2}.txt"`'
test1.txt test2.txt
$ ksh -c 'ls $(echo "test{1,2}.txt")'
test1.txt test2.txt
$ var=nope var1=one var2=two bash -c 'echo $var{1,2}'
one two
$ var=nope var1=one var2=two csh -c 'echo $var{1,2}'
nope1 nope2
Ce dernier exemple est le même csh
, zsh
, ksh93
, mksh
ou fish
.
Notez également que l'expansion d'accolade dans le cadre de la globalisation est également disponible via la glob(3)
fonction de bibliothèque (au moins sur Linux et tous les BSD), et dans d'autres implémentations indépendantes (par exemple, dans perl:) perl -le 'print join " ", <test{1,2}.txt>'
.
Pourquoi cela a été fait différemment dans bash
a probablement une histoire derrière elle, mais FWIW Je n'ai pas pu trouver d'explication logique, et je trouve toutes les rationalisations post-hoc peu convaincantes.