Estoy tratando de expandir una cadena que involucra un comodín y una colección de extensiones especificadas dentro de llaves. Nada parece funcionar como lo ilustra el siguiente ejemplo. la variable se firstList
expande bien, pero tampoco secondList
, thirdList
o se fourthList
expande correctamente. También probé varias versiones eval
pero ninguna funciona. Cualquier ayuda sería apreciada
#!/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
fuente
fuente
eval ls $secondList
funciona bien aquí ... ¿qué estás tratando de lograr?eval
obtener una segunda ronda de expansiones.Respuestas:
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):
Incluso si hay archivos con otros nombres:
¿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).
Podemos desactivar la "expansión de nombre de ruta" por un momento:
La "Expansión del nombre de ruta" recibe dos argumentos:
*.ext1
y*.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
.Los valores de los nombres de archivo no generan problemas de ejecución para eval:
Pero el valor de
$list
podría ser inseguro. Sin embargo,$list
el guionista establece el valor de . El guionista tiene el control deeval
: Simplemente no use valores establecidos externamente para$list
. Prueba esto:Una mejor alternativa
Una alternativa (sin evaluación) es usar Bash "Extended Patterns" :
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.fuente
Considerar:
El problema es que la expansión de llaves se realiza antes de la expansión variable . Eso significa que, en lo anterior, la expansión de llaves nunca se realiza.
Esto se debe a que, cuando bash ve por primera vez la línea de comando, no hay llaves. Después de que
secondList
se expande, ya es demasiado tarde.Lo siguiente funcionará:
Aquí, la línea de comando tiene llaves para que la expansión de llaves se pueda realizar como primer paso. Después de eso, el valor de
$s
se sustituye en ( expansión variable ), y finalmente se realiza la expansión del nombre de ruta .Documentación
man bash
explica el orden de expansión:fuente