La shell si espande *
solo se non quotata, qualsiasi quotazione interrompe l'espansione della shell.
Inoltre, un'espansione di parentesi graffe deve essere annullata per essere espansa dalla shell.
Questo lavoro (usa echo per vedere cosa fa la shell):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Anche se ci sono file con altri nomi:
$ 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
Perché funziona
È importante capire perché funziona. È a causa dell'ordine di espansione. Prima "Espansione parentesi graffa" e poi (l'ultima) "Espansione percorso" (aka espansione globale).
Brace --> Parameter (variable) --> Pathname
Possiamo disattivare "Espansione percorso" per un momento:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
"Pathname Expansion" riceve due argomenti: *.ext1
e *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Il problema è che non possiamo usare una variabile per l'espansione del controvento.
È stato spiegato molte volte in precedenza per l' utilizzo di una variabile all'interno di una "Espansione del rinforzo"
Per espandere un "Espansione del rinforzo" che è il risultato di un "Espansione variabile", è necessario inviare nuovamente la riga di comando alla shell con eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Parentesi graffa -> Variabile -> Glob || -> Parentesi graffa -> Variabile -> Glob
........ citato qui -> ^^^^^^ || eval ^^^^^^^^^^^^^^^^^^^^^^^^^
I valori dei nomi dei file non comportano problemi di esecuzione per eval:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Ma il valore di $list
potrebbe non essere sicuro. Tuttavia, il valore di $list
è impostato dallo script writer. Lo script writer ha il controllo di eval
: Basta non usare valori impostati esternamente per $list
. Prova questo:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Un'alternativa migliore.
Un'alternativa (senza valutazione) è usare Bash "Extended Patterns" :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Nota: tenere presente che entrambe le soluzioni (eval e pattern) (come scritto) sono sicure per i nomi di file con spazi o nuove righe. Ma fallirà per a $list
con spazi, perché $list
non è quotato o eval rimuove le virgolette.
eval ls $secondList
funziona bene qui ... cosa stai cercando di realizzare?