Estou tentando expandir uma string envolvendo um curinga e uma coleção de extensões especificadas dentro de chaves. Nada parece funcionar como o exemplo abaixo ilustra. a variável firstList
expande bem, mas não secondList
, thirdList
ou fourthList
se expande corretamente. Eu também tentei várias versões, eval
mas nenhuma funciona. Qualquer ajuda seria 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
fonte
fonte
eval ls $secondList
funciona bem aqui ... o que você está tentando realizar?eval
obter uma segunda rodada de expansões.Respostas:
O shell se expande
*
apenas se não estiver entre aspas; qualquer aspeto interrompe a expansão pelo shell.Além disso, uma expansão de colchete precisa ser sem aspas para ser expandida pelo shell.
Este trabalho (vamos usar echo para ver o que o shell faz):
Mesmo se houver arquivos com outros nomes:
Por que isso funciona?
É importante que entendamos por que isso funciona. É por causa da ordem de expansão. Primeiro, a "expansão Brace" e depois (a última) "Expansão do nome do caminho" (também conhecida como expansão glob).
Podemos desativar a "expansão do nome do caminho" por um momento:
A "expansão do nome do caminho" recebe dois argumentos:
*.ext1
e*.ext2
.O problema é que não podemos usar uma variável para a expansão de chaves.
Isso já foi explicado várias vezes antes para o uso de uma variável dentro de uma "expansão de chaves"
Para expandir uma "expansão de chave" que é o resultado de uma "expansão variável", é necessário reenviar a linha de comando para o shell com
eval
.Os valores dos nomes dos arquivos não trazem problemas de execução para eval:
Mas o valor de
$list
poderia ser inseguro. No entanto, o valor de$list
é definido pelo escritor do script. O gravador de script está no controle deeval
: Apenas não use valores definidos externamente para$list
. Tente isto:Uma alternativa melhor.
Uma alternativa (sem avaliação) é usar o Bash "Extended Patterns" :
Nota: Esteja ciente de que ambas as soluções (avaliação e padrões) (conforme escritas) são seguras para nomes de arquivos com espaços ou novas linhas. Mas falhará em um
$list
com espaços, porque$list
não está entre aspas ou o eval remove as aspas.fonte
Considerar:
O problema é que a expansão do braquete é feita antes da expansão variável . Isso significa que, acima, a expansão da braçadeira nunca é realizada.
Isso ocorre porque, quando o bash vê pela primeira vez a linha de comando, não há chaves. Depois de
secondList
expandido, é tarde demais.O seguinte funcionará:
Aqui, a linha de comando possui chaves para que a expansão da chave possa ser executada como a primeira etapa. Depois disso, o valor de
$s
é substituído em ( expansão variável ) e, por fim, a expansão do nome do caminho é realizada.Documentação
man bash
explica a ordem da expansão:fonte