Eu estava tentando usar expansões de strings sem aspas para passar dois argumentos para tar; o primeiro é o sinalizador da linha de comando --exclude
e o segundo contém um *
caractere. Na tentativa de evitar globbing prematuro, tentei citar *
:
shopt -s nullglob
x="--exclude '*'"
echo tar $x
Para minha surpresa, '*'
desapareceu completamente! Aqui estava o resultado:
tar --exclude
Entendo que poderia mudar do shell POSIX para o Bash e usar arrays para evitar essa dor de cabeça. Mas ainda me pergunto: o que diabos estava acontecendo com aquele trecho de shell POSIX? Por que ele excluiu os globos citados? Eu esperava que isso deixasse a parte citada em paz ou percorresse todo o caminho e expandisse o globo. Não fez nada disso.
Primeiro de tudo, você já está usando
bash
- ou pelo menos algumas opções não POSIX. (Nemshopt
énullglob
POSIX.)Agora vamos explicar o que aconteceu.
A variável
$x
é dividida em espaços em branco e as partes resultantes são entregues para globbing.--exclude
não tem curinga e é deixado literalmente.'*'
não tem correspondência (a menos que você tenha um nome de arquivo começando e terminando literalmente com aspas simples), porque contém um curinga e você o configurou,nullglob
ele é removido. O resultado éComo você já está usando,
bash
é melhor fazê-lo corretamente,Se você deseja uma solução POSIX, o melhor que posso oferecer é reutilizar a lista de argumentos principais:
Para casos extremos como esse, a ordem das expansões do shell na documentação do Bash geralmente é a causa do comportamento inesperado. Posix tem mais ou menos o mesmo comportamento, mas declarado de forma menos clara.
Aqui está o que está acontecendo:
Você transformou nullglob, então os globs que falharam estão vazios.
Em seguida, você define uma variável contendo um asterisco literal e aspas simples.
Você então repete o conteúdo da variável e as seguintes coisas acontecem:
'*'
'*'
é substituído por qualquer nome de arquivo presente, apesar das aspas simples que você acha que o tornariam apenas uma string literal. Nullglob transforma isso em uma string vazia