O [comando é um comando comum. Embora a maioria dos shells o forneça como um built-in de eficiência, ela obedece às regras sintáticas normais do shell. [é exatamente equivalente a test, exceto que [requer a ]como seu último argumento e testnão.
Os colchetes duplos [[ … ]]são sintaxe especial. Eles foram introduzidos no ksh (vários anos depois [) porque [podem ser problemáticos de usar corretamente e [[permitem algumas novas adições interessantes que usam caracteres especiais do shell. Por exemplo, você pode escrever
[[ $x = foo && $y = bar ]]
porque toda a expressão condicional é analisada pelo shell, enquanto [ $x = foo && $y = bar ]que primeiro seria dividida em dois comandos [ $x = fooe $y = bar ]separada pelo &&operador. Da mesma forma, colchetes duplos permitem coisas como a sintaxe de correspondência de padrões, por exemplo, [[ $x == a* ]]para testar se o valor de xcomeça com a; entre colchetes, isso seria expandido a*para a lista de arquivos cujos nomes começam ano diretório atual. Os colchetes duplos foram introduzidos pela primeira vez no ksh e só estão disponíveis no ksh, bash e zsh.
Dentro de colchetes, você precisa usar aspas duplas em torno de substituições de variáveis, como na maioria dos outros lugares, porque são apenas argumentos para um comando (que por acaso é o [comando). Dentro de colchetes duplos, você não precisa de aspas duplas, porque o shell não divide ou brilha palavras: está analisando uma expressão condicional, não um comando.
Uma exceção, porém, é [[ $var1 = "$var2" ]]onde você precisa das aspas, se desejar fazer uma comparação de cadeias de bytes a bytes, caso contrário, $var2seria um padrão com o qual comparar $var1.
Uma coisa que você não pode fazer [[ … ]]é usar uma variável como operador. Por exemplo, isso é perfeitamente legal (mas raramente útil):
if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
…
if [ "$x" "$op" "$y" ]; then …
No seu exemplo
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …
o comando dentro do ifé [com os 4 argumentos -d, /home/mazimi/VirtualBox, VMse ]. O shell analisa -d /home/mazimi/VirtualBoxe depois não sabe o que fazer VMs. Você precisaria impedir a divisão de palavras ${dir}para obter um comando bem formado.
De um modo geral, sempre use aspas duplas em torno de substituições de variáveis e comandos, a menos que você saiba que deseja executar a divisão e a observação de palavras no resultado. Os principais locais onde é seguro não usar aspas duplas são:
- em uma atribuição:
foo=$bar(mas observe que você precisa de aspas duplas em export "foo=$bar"ou em atribuições de matriz como array=("$a" "$b"));
- em uma
casedeclaração case $foo in …:;
- dentro de colchetes duplos, exceto no lado direito da
=ou ==operador (a menos que você deseja fazer a correspondência de padrões): [[ $x = "$y" ]].
Em tudo isso, é correto usar aspas duplas, assim você pode pular as regras avançadas e usá-las o tempo todo.