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 test
non 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 = foo
e $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 x
inizia con a
; tra parentesi singole questo si espanderebbe a*
all'elenco dei file i cui nomi iniziano con a
nella 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 $var2
sarebbe un modello con cui $var1
confrontarsi.
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 if
sia [
con i 4 argomenti -d
, /home/mazimi/VirtualBox
, VMs
e ]
. La shell analizza -d /home/mazimi/VirtualBox
e 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
case
dichiarazione 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.