Eu li que é uma prática recomendada colocar aspas duplas em todas as suas expansões variáveis no Bash. Eu também li que não se pode usar um shell glob (curinga ( *
)) logo após uma expansão de variável com aspas duplas. Essas situações entram em conflito quando se deseja usar o valor de um padrão regex, expandido de uma variável.
A razão pela qual às vezes eu gostaria de combinar regex com um curinga é manter meu regex mínimo, mais organizado, de acordo com meu gosto pessoal.
meu problema particular
Baixei o phpmyadmin no diretório raiz do meu documento e o descompactei, mas não consigo renomeá-lo mv
por um padrão regex que coloquei em uma variável e disponível ao expandir sua variável. Aqui está o rastreamento exato:
userName@compName:/var/www/html# ll
total 11336
drwxr-xr-x 3 root root 4096 Feb 14 07:04 ./
drwxr-xr-x 3 root root 4096 Feb 14 06:56 ../
-rw-r--r-- 1 root root 612 Feb 14 06:57 index.nginx-debian.html
drwxr-xr-x 12 root root 4096 Dec 23 08:50 phpMyAdmin-4.7.7-all-languages/
-rw-r--r-- 1 root root 11589684 Dec 23 14:08 phpMyAdmin-latest-all-languages.zip
userName@compName:/var/www/html# echo $pma
[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]
userName@compName:/var/www/html# mv "$pma"*/ phpmyadmin/
mv: cannot stat '[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]*/': No such file or directory
Se eu tirar as aspas da expansão variável, ${pma}
eu realmente seria capaz de combinar a expansão variável e o regex, como em ${pma}*
, mas é importante para mim seguir as melhores práticas sem exceções, se puder.
Minha pergunta
Como eu poderia manter a expansão da variável com aspas duplas, mas ainda usando o valor extraído com um curinga?
Um padrão de globbing de nome de arquivo mantido em uma variável não irá globar nomes de arquivos se houver aspas duplas. São as aspas duplas que impedem que os nomes dos arquivos sejam globbed, não o
*
curinga no final ou a combinação de aspas e*
.Costumamos dizer aos usuários no site para "citar suas variáveis", e fazemos isso porque os valores das variáveis sem aspas passam por divisão de palavras e agrupamento de nomes de arquivos, e isso geralmente não é o que se deseja. Por exemplo, uma senha pode ser
[hello] world*
e em uma linha de comando contendo-p $password
isso faria coisas "interessantes" dependendo de quais arquivos estavam presentes no diretório atual (e pode muito bem não funcionar devido ao espaço). Veja também a questão " Implicações de segurança de esquecer de citar uma variável em bash/POSIX shells "O que você quer fazer aqui é o oposto do que normalmente queremos evitar , ou seja, invocar a inclusão de nome de arquivo usando o padrão de inclusão de nome de arquivo em sua variável.
Se você realmente não pode confiar no nome do diretório extraído para permanecer estável, uma solução melhor (como em "mais limpo") seria possivelmente certificar-se de que é a única coisa em um diretório temporário e, em seguida, apenas use
*
para mover no lugar (possivelmente mudando seu nome no processo, para que você saiba com certeza como é chamado).Isso é melhor do que simplesmente remover as aspas em torno de sua variável, pois o padrão de globbing do nome do arquivo pode corresponder a outros nomes além do único que você espera, dependendo de quais outras coisas estão disponíveis no diretório.
Esta é uma variação da minha resposta à sua pergunta anterior :
O acima pode ser destilado em cinco etapas:
Você não poderia 1 e não quer ; seu comando funciona perfeitamente bem sem eles (e tenho quase certeza de que isso também foi apontado em uma das variantes excluídas anteriormente desta pergunta).
O objetivo de citar suas variáveis é garantir que o shell globbing e a divisão de campos não aconteçam. Desta vez, você realmente deseja que isso aconteça, portanto, citar é contraproducente.
Vale a pena entender porque essas diretrizes existem; elas não são regras gerais e, se não estiverem funcionando para você, você pode estar em uma situação em que não se aplicam. Esforçar-se para "seguir as melhores práticas sem exceções" sem entendê-las é totalmente errado.
Fora isso, isso:
não é verdade.
1 Você poderia usar
eval
, mas seria tão inútil que não vou continuar com isso.