El shell se expande *
solo si no se cita, cualquier cita detiene la expansión del shell.
Además, una expansión de llaves debe estar sin comillas para que el shell la expanda.
Este trabajo (usemos echo para ver qué hace el shell):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Incluso si hay archivos con otros nombres:
$ 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
¿Por qué eso funciona?
Es importante que comprendamos por qué eso funciona. Es por el orden de expansión. Primero la "Expansión de la llave" y luego (la última) "Expansión del nombre de ruta" (también conocida como expansión global).
Brace --> Parameter (variable) --> Pathname
Podemos desactivar la "expansión de nombre de ruta" por un momento:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
La "Expansión del nombre de ruta" recibe dos argumentos: *.ext1
y *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
El problema es que no podemos usar una variable para la expansión de llaves.
Se ha explicado muchas veces antes para usar una variable dentro de una "Expansión de llaves"
Para expandir una "Expansión de llaves" que es el resultado de una "Expansión variable", debe volver a enviar la línea de comando al shell con eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Brace -> Variable -> Glob || -> Brace -> Variable -> Glob
........ citado aquí -> ^^^^^^ || eval ^^^^^^^^^^^^^^^^^^^^^^^^^
Los valores de los nombres de archivo no generan problemas de ejecución para eval:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Pero el valor de $list
podría ser inseguro. Sin embargo, $list
el guionista establece el valor de . El guionista tiene el control de eval
: Simplemente no use valores establecidos externamente para $list
. Prueba esto:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Una mejor alternativa
Una alternativa (sin evaluación) es usar Bash "Extended Patterns" :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Nota: Tenga en cuenta que ambas soluciones (eval y patrones) (tal como están escritas) son seguras para los nombres de archivo con espacios o líneas nuevas. Pero fallará para a $list
con espacios, porque $list
no está entre comillas o la evaluación elimina las comillas.
eval ls $secondList
funciona bien aquí ... ¿qué estás tratando de lograr?