Il [comando è un comando normale. Sebbene la maggior parte delle shell lo fornisca come integrato per l'efficienza, obbedisce alle normali regole sintattiche della shell. [è esattamente equivalente a test, tranne per il fatto che [richiede a ]come ultimo argomento e testnon lo fa.
Le parentesi doppie [[ … ]]sono una sintassi speciale. Sono stati introdotti in ksh (diversi anni dopo [) perché [possono essere fastidiosi da usare correttamente e [[consentono alcune nuove belle aggiunte che usano caratteri speciali della shell. Ad esempio, puoi scrivere
[[ $x = foo && $y = bar ]]
perché l'intera espressione condizionale è analizzata dalla shell, mentre [ $x = foo && $y = bar ]sarebbe prima divisa in due comandi [ $x = fooe $y = bar ]separata &&dall'operatore. Allo stesso modo le doppie parentesi consentono cose come la sintassi di corrispondenza del modello, ad esempio [[ $x == a* ]]per verificare se il valore di xinizia con a; tra parentesi singole questo si espanderebbe a*all'elenco dei file i cui nomi iniziano con anella directory corrente. Le parentesi doppie sono state introdotte per la prima volta in ksh e sono disponibili solo in ksh, bash e zsh.
All'interno di parentesi singole, è necessario utilizzare virgolette doppie intorno alle sostituzioni variabili, come nella maggior parte degli altri posti, perché sono solo argomenti di un comando (che sembra essere il [comando). All'interno di doppie parentesi, non hai bisogno di doppie virgolette, perché la shell non fa divisione di parole o globbing: analizza un'espressione condizionale, non un comando.
Un'eccezione, tuttavia, è quella in [[ $var1 = "$var2" ]]cui sono necessarie le virgolette se si desidera eseguire un confronto tra stringhe byte-byte, altrimenti $var2sarebbe un modello con cui $var1confrontarsi.
Una cosa che non puoi fare [[ … ]]è usare una variabile come operatore. Ad esempio, questo è perfettamente legale (ma raramente utile):
if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
…
if [ "$x" "$op" "$y" ]; then …
Nel tuo esempio
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …
il comando all'interno ifsia [con i 4 argomenti -d, /home/mazimi/VirtualBox, VMse ]. La shell analizza -d /home/mazimi/VirtualBoxe quindi non sa cosa fare VMs. Dovresti impedire la divisione delle parole ${dir}per ottenere un comando ben formato.
In generale, usa sempre le doppie virgolette attorno alle sostituzioni di variabili e comandi a meno che tu non sappia che vuoi eseguire la divisione delle parole e il globbing sul risultato. I luoghi principali in cui è sicuro non usare le doppie virgolette sono:
- in un compito:
foo=$bar(ma tieni presente che hai bisogno delle doppie virgolette in export "foo=$bar"o in compiti di array come array=("$a" "$b"));
- in una
casedichiarazione case $foo in …:;
- tra doppie parentesi tranne sul lato destro della
=o ==dell'operatore (a meno che non si vuole pattern matching): [[ $x = "$y" ]].
In tutti questi, è corretto usare le virgolette doppie, quindi potresti anche saltare le regole avanzate e usare le virgolette continuamente.