Bash scripting - comandi essenziali: differenze tra le versioni

Da Guide@Debianizzati.Org.
Vai alla navigazione Vai alla ricerca
(- template "Versioni compatibili")
m (Correzione maiuscola-minuscola)
 
(12 versioni intermedie di 3 utenti non mostrate)
Riga 1: Riga 1:
{{Bash_scripting}}
{{Bash scripting}}
=Comandi essenziali=
__TOC__
I comandi introdotti in questa sezione sono descritti solo limitatamente alla loro sintassi base, così che il loro impiego nelle sezioni successive possa essere facilmente compreso.
I comandi introdotti in questa sezione sono descritti solo limitatamente alla loro sintassi base, così che il loro impiego nelle sezioni successive possa essere facilmente compreso.


La lettura della sezione può essere tralasciata, se si hanno già nozioni basilari di '''bash''', ma la parte sui comandi di output serve anche a giustificare la scelta di <code>printf</code> in luogo del più noto <code>echo</code> come unico comando di output e a spiegarne brevemente la sintassi, almeno per le invocazioni più comuni.
La lettura della sezione può essere tralasciata, se si hanno già nozioni basilari di '''bash''', ma la parte sui comandi di output serve anche a giustificare la scelta di <code>printf</code> in luogo del più noto <code>echo</code> come unico comando di output e a spiegarne brevemente la sintassi, almeno per le invocazioni più comuni.


==Comandi di output: echo e printf==
== Comandi di output: echo e printf ==
Il comando <code>echo</code> è largamente diffuso in Bash per stampare delle stringhe su schermo, perché ha una sintassi più semplice di <code>printf</code> e non risente delle stesse limitazioni della shell sh (''POSIX''), che interpreta ed espande i caratteri di escape (si legga la sezione dedicata) senza che ci sia un modo di stampare letteralmente una stringa (non nota a priori).
Il comando <code>echo</code> è largamente diffuso in Bash per stampare delle stringhe su schermo, perché ha una sintassi più semplice di <code>printf</code> e non risente delle stesse limitazioni della shell sh (''[[POSIX]]''), che interpreta ed espande i caratteri di escape (si legga la sezione dedicata) senza che ci sia un modo di stampare letteralmente una stringa (non nota a priori).


Tuttavia negli script l'uso di <code>echo</code> non è sempre possibile, rendendo necessaria la conoscenza almeno basilare di <code>printf</code>. In particolare, se si vuole stampare il contenuto di $var, '''non''' è sempre corretto scrivere:
Tuttavia negli script l'uso di <code>echo</code> non è sempre possibile, rendendo necessaria la conoscenza almeno basilare di <code>printf</code>. In particolare, se si vuole stampare il contenuto di $var, '''non''' è sempre corretto scrivere:
Riga 19: Riga 19:
In questa guida d'ora in poi si farà riferimento soltanto a <code>printf</code>.
In questa guida d'ora in poi si farà riferimento soltanto a <code>printf</code>.


===Uso di printf===
=== Uso di printf ===
Sintassi: <code>printf formato [ "stringa" ... ]</code>
Sintassi: <code>printf formato [ "stringa" ... ]</code>


Riga 69: Riga 69:
</pre>
</pre>


==Condizioni==
==== Stampa di messagi d'errore ====
Per i messaggi di errore, benché sia possibile stamparli assieme ai messaggi normali (sullo ''standard output''), è conveniente utilizzare lo ''standard error'' che ne permette la gestione separata. Se nessuna redirezione è specificata, saranno comunque stampati a schermo a prescindere dall'uso di ''standard output'', che è implicito, o ''standard error''.
 
Il significato delle redirezioni sarà trattato in seguito in un capitolo apposito della guida. Per ora e per buona parte della guida basti sapere che per stampare messaggi di errore è sufficiente aggiungere '''>&2''' al termine dell'istruzione <code>printf</code>.
 
Per esempio:
<pre>
printf %s\\n "ERRORE: il file specificato non esiste!" >&2  # standard error
</pre>
 
==== Sovrascrivere echo ====
Se non si riesce a fare a meno di <code>echo</code> si può sovrascriverlo per gli usi più basilari, così da utilizzare al suo posto <code>printf</code> in modo trasparente, mettendo queste definizioni in cima allo script subito dopo lo ''shebang'':
<pre>
# sovrascrivo echo
# stampa su schermo con "a capo" finale
echo () { printf %s\\n "$*" ; }
 
# rimpiazzo per echo -n
# stampa su schermo senza "a capo" finale)
echo_n () { printf %s "$*" ; }
</pre>
 
Per esempio:
<pre>
#! /bin/bash
 
# sovrascrivo echo
echo () { printf %s\\n "$*" ; }
 
# al posto di echo -n
echo_n () { printf %s "$*" ; }
 
# ora si può usare echo (echo_n) al posto di printf %s\\n (printf %s)
 
echo "Hello World!"  # stampa: Hello World!
echo_n "Hello world!" # stampa: Hello world! (senza "a capo")
echo -n              # stampa: -n
echo -e              # stampa: -e
 
exit 0
</pre>
 
== Condizioni ==
Le condizioni nella shell dipendono dal valore di uscita (exit status) di un comando. Si considera successo un exit status corrispondente a 0, ed è equivalente a una condizione vera/soddisfatta, mentre fallimento un exit status con valori diversi da zero, e sono equivalenti a una condizione falsa/non soddisfatta.
Le condizioni nella shell dipendono dal valore di uscita (exit status) di un comando. Si considera successo un exit status corrispondente a 0, ed è equivalente a una condizione vera/soddisfatta, mentre fallimento un exit status con valori diversi da zero, e sono equivalenti a una condizione falsa/non soddisfatta.


Riga 87: Riga 129:
</pre>
</pre>


===Espressioni booleane===
=== Espressioni booleane ===
Le espressioni booleane più basilari, ereditate da ''POSIX'', si possono esprimere con i comandi <code>test</code> e <code>[</code>. L'unica differenza tra i due è che il secondo richiede <code>]</code> come ultimo argomento, ed è preferibile per questioni di leggibilità del codice. D'ora in poi infatti si considera soltanto <code>[ ... ]</code>, e in questa sezione vengono descritte solo le forme più basilari. Per tutte le opzioni supportate si rimanda all'aiuto integrato (<code>help test</code>).
Le espressioni booleane più basilari, ereditate da ''POSIX'', si possono esprimere con i comandi <code>test</code> e <code>[</code>. L'unica differenza tra i due è che il secondo richiede <code>]</code> come ultimo argomento, ed è preferibile per questioni di leggibilità del codice. D'ora in poi infatti si considera soltanto <code>[ ... ]</code>, e in questa sezione vengono descritte solo le forme più basilari. Per tutte le opzioni supportate si rimanda all'aiuto integrato (<code>help test</code>).


Riga 99: Riga 141:
* <code>[ "$var" = "stringa" ]</code>: vero se il contenuto di var è uguale alla stringa;
* <code>[ "$var" = "stringa" ]</code>: vero se il contenuto di var è uguale alla stringa;
* <code>[ "$var" != "stringa" ]</code>: vero se è diverso.
* <code>[ "$var" != "stringa" ]</code>: vero se è diverso.
Su '''bash''' si può usare anche <code>==</code> al posto di <code>=</code>, per chi ha familiarità con la sintassi dei confronti C-like, ma non è ''POSIX''.


Confronti binari tra stringhe contenenti interi (possono essere anche entrambe variabili):
Confronti binari tra stringhe contenenti interi (possono essere anche entrambe variabili):
* <code>[ "$var" -eq valore ]</code>: ('''eq'''ual to) vero se l'intero contenuto nella variabile è uguale al valore dato;
* <code>[ "$var" -ne valore ]</code>: ('''n'''ot '''e'''qual to) vero se l'intero contenuto nella variabile non è uguale al valore dato;
* <code>[ "$var" -gt valore ]</code>: ('''g'''reater '''t'''han) vero se l'intero contenuto nella variabile è maggiore del valore dato;
* <code>[ "$var" -gt valore ]</code>: ('''g'''reater '''t'''han) vero se l'intero contenuto nella variabile è maggiore del valore dato;
* <code>[ "$var" -ge valore ]</code>: ('''g'''reater or '''e'''qual to) vero se l'intero contenuto nella variabile è maggiore o uguale al valore dato;
* <code>[ "$var" -ge valore ]</code>: ('''g'''reater or '''e'''qual to) vero se l'intero contenuto nella variabile è maggiore o uguale al valore dato;
* <code>[ "$var" -lt valore ]</code>: ('''l'''ower '''t'''han) vero se l'intero contenuto nella variabile è inferiore del valore dato.
* <code>[ "$var" -lt valore ]</code>: ('''l'''ower '''t'''han) vero se l'intero contenuto nella variabile è inferiore del valore dato.
* <code>[ "$var" -le valore ]</code>: ('''l'''ower or '''e'''qual to) vero se l'intero contenuto nella variabile è inferiore o uguale al valore dato.
* <code>[ "$var" -le valore ]</code>: ('''l'''ower or '''e'''qual to) vero se l'intero contenuto nella variabile è inferiore o uguale al valore dato.
Se una delle due stringhe non è un intero, anche negativo, il confronto fallisce e può esserci la stampa di un messaggio d'errore sullo standard error. Per evitarlo va aggiunto <code>2> /dev/null</code> (il significato di tale redirezione sarà trattato in seguito). Per esempio:
Se una delle due stringhe non è un intero, anche negativo, il confronto fallisce e può esserci la stampa di un messaggio d'errore sullo standard error. Per evitarlo va aggiunto '''2> /dev/null''' (il significato di tale redirezione sarà trattato in seguito).
 
Per esempio:
<pre>
<pre>
[ "$var" -gt 0 ] 2> /dev/null # non stampa errori se $var non è un intero
# Controlla che la variabile sia un intero non negativo
[ "$var" -ge 0 ] 2> /dev/null     # non stampa errori se $var non è un intero
# Controlla che la variabile sia un intero qualsiasi
[ "$var" -eq "$var" ] 2> /dev/null # fallisce solo se $var non è intero
</pre>
</pre>


Confronti unari con stringhe contenenti percorsi di file (percorso di default: directory corrente, se mancante):
Confronti unari con stringhe contenenti percorsi di file (percorso di default: directory corrente, se mancante):
* <code>[ -b "$var" ]</code>: vero se il file è un dispositivo a blocchi;
* <code>[ -c "$var" ]</code>: vero se il file è un dispositivo a caratteri;
* <code>[ -d "$var" ]</code>: vero se il file esiste ed è una directory;
* <code>[ -e "$var" ]</code>: vero se il file (file regolare, directory, link simbolico, fifo, socket, ... ) esiste;
* <code>[ -e "$var" ]</code>: vero se il file (file regolare, directory, link simbolico, fifo, socket, ... ) esiste;
* <code>[ -f "$var" ]</code>: vero se il file esiste ed è un file regolare;
* <code>[ -f "$var" ]</code>: vero se il file esiste ed è un file regolare;
* <code>[ -d "$var" ]</code>: vero se il file esiste ed è una directory.
* <code>[ -g "$var" ]</code>: vero se è impostato il bit sgid;
* <code>[ -G "$var" ]</code>: vero se l’id di gruppo del file è uguale al vostro;
* <code>[ -h "$var" ]</code>: vero se il file esiste ed è un link simbolico;
* <code>[ -k "$var" ]</code>: vero se è impostato lo “sticky bit”;
* <code>[ -L "$var" ]</code>: vero se il file esiste ed è un link simbolico;
* <code>[ -N "$var" ]</code>: vero se il file è stato modificato dall’ultima lettura;
* <code>[ -O "$var" ]</code>: vero se si è il proprietario del file;
*<code>[ -p "$var" ]</code>: vero se il file è una pipe (FIFO);
* <code>[ -r "$var" ]</code>: vero se il file esiste e l'utente corrente ha il permesso di lettura;
*<code>[ -s "$var" ]</code>: vero se il file non è vuoto;
* <code>[ -S "$var" ]</code>: vero se il file è un socket;
* <code>[ -t "$var" ]</code>: vero se il file è associato a un terminale;
* <code>[ -u "$var" ]</code>: vero se è impostato il bit suid;
* <code>[ -w "$var" ]</code>: vero se il file esiste e l'utente corrente ha il permesso di scrittura;
* <code>[ -x "$var" ]</code>: vero se il file esiste e l'utente corrente ha il permesso di esecuzione (o accesso per le directory).
Confronti binari con stringhe contenenti percorsi di file:


Le espressioni più complesse si possono comporre utilizzando gli operatori logici <code>&&</code> e <code>||</code> per aggregare più istruzioni <code>[...]</code>, e le parentesi <code>{ ... ; }</code> per determinarne la priorità, come si vedrà nella parte sui blocchi di istruzioni.
* <code>[ "$var1" -nt "$var2" ]</code>: vero se il file $var1 è più recente di $var2;
*<code>[ "$var1" -ot "$var2" ]</code>: vero se il file $var1 è più vecchio di $var2;
* <code>[ "$var1" -et "$var2" ]</code>: vero se i file $var1 e $var2 sono degli hard link allo stesso file;


===Esecuzione condizionata===
Con il punto esclamativo <code>!</code> (NOT) si inverte il senso dei precedenti confronti.
 
=== Esecuzione condizionata ===
Per eseguire un blocco di comandi soltanto se una condizione è soddisfatta si utilizza <code>if</code>, solitamente in combinazione con <code>[...]</code>.
Per eseguire un blocco di comandi soltanto se una condizione è soddisfatta si utilizza <code>if</code>, solitamente in combinazione con <code>[...]</code>.


Riga 143: Riga 215:
</pre>
</pre>


====Controllo degli errori====
==== Controllo degli errori ====
Si ricordi che <code>if</code> accetta un comando qualsiasi come condizione, valutandone l'exit status ed eseguendo il ramo <code>then</code> se ha successo, e quello <code>elif</code>/<code>else</code> immediatamente successivo (se presente) altrimenti. Quindi è un ottimo strumento anche per controllare che un comando venga eseguito senza errori, permettendo anche la terminazione immediata dello script:
Si ricordi che <code>if</code> accetta un comando qualsiasi come condizione, valutandone l'exit status ed eseguendo il ramo <code>then</code> se ha successo, e quello <code>elif</code>/<code>else</code> immediatamente successivo (se presente) altrimenti. Quindi è un ottimo strumento anche per controllare che un comando venga eseguito senza errori, permettendo anche la terminazione immediata dello script:
<pre>
<pre>
Riga 149: Riga 221:
   printf %s\\n "Comando riuscito!"
   printf %s\\n "Comando riuscito!"
else
else
   printf %s\\n "ERRORE: comando fallito!"
   printf %s\\n "ERRORE: comando fallito!" >&2  # stampa sullo standard error
   # esci con errore (exit status 1)
   # esci con errore (exit status 1)
   exit 1
   exit 1
fi
fi
</pre>
</pre>
e se si è interessati al solo ramo ''else'', basta utilizzare <code>!</code> prima del comando:
 
E se si è interessati al solo ramo ''else'', basta utilizzare <code>!</code> prima del comando:
<pre>
<pre>
if ! comando; then
if ! comando; then
Riga 160: Riga 233:
fi
fi
</pre>
</pre>
{{Autori
|Autore=[[Utente:HAL 9000|HAL 9000]] 12:56, 22 lug 2014 (CEST)
}}


[[Categoria:Bash]][[Categoria:Bash_Scripting]]
[[Categoria:Bash]][[Categoria:Bash_Scripting]]

Versione attuale delle 14:04, 25 giu 2022

Bash scripting

Sommario

  1. Introduzione
  2. Comandi essenziali
  3. Variabili (stringhe)
  4. Caratteri di escape, apici e virgolette
  5. Espansioni in stringhe quotate
  6. Espansioni non quotabili
  7. Istruzioni composte
  8. Funzioni
  9. File descriptor e redirezioni
  10. Segnali

I comandi introdotti in questa sezione sono descritti solo limitatamente alla loro sintassi base, così che il loro impiego nelle sezioni successive possa essere facilmente compreso.

La lettura della sezione può essere tralasciata, se si hanno già nozioni basilari di bash, ma la parte sui comandi di output serve anche a giustificare la scelta di printf in luogo del più noto echo come unico comando di output e a spiegarne brevemente la sintassi, almeno per le invocazioni più comuni.

Comandi di output: echo e printf

Il comando echo è largamente diffuso in Bash per stampare delle stringhe su schermo, perché ha una sintassi più semplice di printf e non risente delle stesse limitazioni della shell sh (POSIX), che interpreta ed espande i caratteri di escape (si legga la sezione dedicata) senza che ci sia un modo di stampare letteralmente una stringa (non nota a priori).

Tuttavia negli script l'uso di echo non è sempre possibile, rendendo necessaria la conoscenza almeno basilare di printf. In particolare, se si vuole stampare il contenuto di $var, non è sempre corretto scrivere:

echo -n "$var" # stampa senza a capo finale
echo "$var"    # stampa con a capo finale

perché $var potrebbe iniziare con il carattere "-" ed essere una combinazione delle opzioni: -e, -E, -n.

Con echo non esiste un modo che assicuri la stampa del contenuto di una variabile in ogni situazione possibile. E non sempre il contenuto è noto a priori: in presenza di espansioni, come vedremo poi, o di input dell'utente. Per non incorrere in errori difficili da riconoscere, echo andrebbe usato soltanto nella shell interattiva, dove l'uso è più comodo, e printf andrebbe preferito anche in Bash per gli script, perché ha una sintassi più robusta.

In questa guida d'ora in poi si farà riferimento soltanto a printf.

Uso di printf

Sintassi: printf formato [ "stringa" ... ]

Gli usi più avanzati non sono trattati in questa guida, ma di seguito sono presentati alcuni esempi:

  • stampa sullo schermo senza a capo finale
printf %s "stringa da stampare"
printf %s "$var"
  • stampa una riga vuota
printf \\n   # corretto (doppio backslash)
printf \n    # ERRORE: stampa 'n'

# tra virgolette
printf "\\n" # corretto (doppio backslash)
printf "\n"  # corretto (singolo backslash)

# tra apici
printf '\\n' # ERRORE: stampa '\n'
printf '\n'  # corretto (singolo backslash)
  • altri caratteri speciali nel formato (stesse considerazioni sull'uso di " e ')
printf \\t   # tabulazione
printf \\r   # ritorno a inizio riga
printf \\NNN # stampa il carattere ascii con codice in base 8
  • stampa sullo schermo con a capo finale
printf %s\\n "stringa da stampare"
printf %s\\n "$var"
  • stampa con a capo prima e dopo
printf \\n%s\\n "stringa" 

Mai stampare una stringa e ancora peggio una variabile senza farla precedere dal formato:

printf "stringa"    # ERRORE: le sequenze speciali inizianti in \ e % verrebbero interpretate!
printf "$var"       # ERRORE: come sopra
printf %s "stringa" # corretto
printf %s "$var"    # corretto

Per usi più complessi, anziché rendere più complicato il formato, è preferibile utilizzare più comandi printf:

# funziona, ma è poco chiaro per chi non ne conosce la sintassi
printf '%s\n\t%s  %s\n' "Sintassi:" "$0" "[ arg ]" # più stringhe

# equivalente, ma più leggibile:
printf %s\\n "Sintassi:"
printf '\t%s\n' "$0  [ arg ]"

Stampa di messagi d'errore

Per i messaggi di errore, benché sia possibile stamparli assieme ai messaggi normali (sullo standard output), è conveniente utilizzare lo standard error che ne permette la gestione separata. Se nessuna redirezione è specificata, saranno comunque stampati a schermo a prescindere dall'uso di standard output, che è implicito, o standard error.

Il significato delle redirezioni sarà trattato in seguito in un capitolo apposito della guida. Per ora e per buona parte della guida basti sapere che per stampare messaggi di errore è sufficiente aggiungere >&2 al termine dell'istruzione printf.

Per esempio:

printf %s\\n "ERRORE: il file specificato non esiste!" >&2  # standard error

Sovrascrivere echo

Se non si riesce a fare a meno di echo si può sovrascriverlo per gli usi più basilari, così da utilizzare al suo posto printf in modo trasparente, mettendo queste definizioni in cima allo script subito dopo lo shebang:

# sovrascrivo echo
# stampa su schermo con "a capo" finale
echo () { printf %s\\n "$*" ; }

# rimpiazzo per echo -n
# stampa su schermo senza "a capo" finale)
echo_n () { printf %s "$*" ; }

Per esempio:

#! /bin/bash

# sovrascrivo echo
echo () { printf %s\\n "$*" ; }

# al posto di echo -n
echo_n () { printf %s "$*" ; }

# ora si può usare echo (echo_n) al posto di printf %s\\n (printf %s)

echo "Hello World!"   # stampa: Hello World!
echo_n "Hello world!" # stampa: Hello world! (senza "a capo")
echo -n               # stampa: -n
echo -e               # stampa: -e

exit 0

Condizioni

Le condizioni nella shell dipendono dal valore di uscita (exit status) di un comando. Si considera successo un exit status corrispondente a 0, ed è equivalente a una condizione vera/soddisfatta, mentre fallimento un exit status con valori diversi da zero, e sono equivalenti a una condizione falsa/non soddisfatta.

Il significato dell'exit status di un comando (successo/fallimento) può essere invertito facendolo precedere da un punto esclamativo (!).

Alcuni comandi hanno un exit status predeterminato:

  • : o (equivalentemente) true hanno un exit status sempre di zero (successo/vero);
  • false ha un exit status sempre diverso da zero (fallimento/falso).

Per esempio:

:       # exit status 0
true    # equivalente
! :     # exit status diverso da 0
false   # exit status diverso da 0
! false # exit status 0

Espressioni booleane

Le espressioni booleane più basilari, ereditate da POSIX, si possono esprimere con i comandi test e [. L'unica differenza tra i due è che il secondo richiede ] come ultimo argomento, ed è preferibile per questioni di leggibilità del codice. D'ora in poi infatti si considera soltanto [ ... ], e in questa sezione vengono descritte solo le forme più basilari. Per tutte le opzioni supportate si rimanda all'aiuto integrato (help test).

Il comando [...] restituisce un exit status di 0 (successo/vero) se la condizione contenuta all'interno è vera, e 1 (fallimento/falso) altrimenti. È molto utile all'interno di istruzioni più complesse, come if per l'esecuzione condizionata e while per eseguire cicli.

Confronti unari con stringhe (tipicamente l'espansione di variabile o parametro):

  • [ -z "$var" ]: vero se var contiene una stringa di lunghezza zero o non è definita;
  • [ -n "$var" ]: vero se var contiene una stringa che non ha lunghezza zero.

Confronti binari tra stringhe (possono essere anche entrambe variabili):

  • [ "$var" = "stringa" ]: vero se il contenuto di var è uguale alla stringa;
  • [ "$var" != "stringa" ]: vero se è diverso.

Su bash si può usare anche == al posto di =, per chi ha familiarità con la sintassi dei confronti C-like, ma non è POSIX.

Confronti binari tra stringhe contenenti interi (possono essere anche entrambe variabili):

  • [ "$var" -eq valore ]: (equal to) vero se l'intero contenuto nella variabile è uguale al valore dato;
  • [ "$var" -ne valore ]: (not equal to) vero se l'intero contenuto nella variabile non è uguale al valore dato;
  • [ "$var" -gt valore ]: (greater than) vero se l'intero contenuto nella variabile è maggiore del valore dato;
  • [ "$var" -ge valore ]: (greater or equal to) vero se l'intero contenuto nella variabile è maggiore o uguale al valore dato;
  • [ "$var" -lt valore ]: (lower than) vero se l'intero contenuto nella variabile è inferiore del valore dato.
  • [ "$var" -le valore ]: (lower or equal to) vero se l'intero contenuto nella variabile è inferiore o uguale al valore dato.

Se una delle due stringhe non è un intero, anche negativo, il confronto fallisce e può esserci la stampa di un messaggio d'errore sullo standard error. Per evitarlo va aggiunto 2> /dev/null (il significato di tale redirezione sarà trattato in seguito).

Per esempio:

# Controlla che la variabile sia un intero non negativo
[ "$var" -ge 0 ] 2> /dev/null      # non stampa errori se $var non è un intero
# Controlla che la variabile sia un intero qualsiasi
[ "$var" -eq "$var" ] 2> /dev/null # fallisce solo se $var non è intero

Confronti unari con stringhe contenenti percorsi di file (percorso di default: directory corrente, se mancante):

  • [ -b "$var" ]: vero se il file è un dispositivo a blocchi;
  • [ -c "$var" ]: vero se il file è un dispositivo a caratteri;
  • [ -d "$var" ]: vero se il file esiste ed è una directory;
  • [ -e "$var" ]: vero se il file (file regolare, directory, link simbolico, fifo, socket, ... ) esiste;
  • [ -f "$var" ]: vero se il file esiste ed è un file regolare;
  • [ -g "$var" ]: vero se è impostato il bit sgid;
  • [ -G "$var" ]: vero se l’id di gruppo del file è uguale al vostro;
  • [ -h "$var" ]: vero se il file esiste ed è un link simbolico;
  • [ -k "$var" ]: vero se è impostato lo “sticky bit”;
  • [ -L "$var" ]: vero se il file esiste ed è un link simbolico;
  • [ -N "$var" ]: vero se il file è stato modificato dall’ultima lettura;
  • [ -O "$var" ]: vero se si è il proprietario del file;
  • [ -p "$var" ]: vero se il file è una pipe (FIFO);
  • [ -r "$var" ]: vero se il file esiste e l'utente corrente ha il permesso di lettura;
  • [ -s "$var" ]: vero se il file non è vuoto;
  • [ -S "$var" ]: vero se il file è un socket;
  • [ -t "$var" ]: vero se il file è associato a un terminale;
  • [ -u "$var" ]: vero se è impostato il bit suid;
  • [ -w "$var" ]: vero se il file esiste e l'utente corrente ha il permesso di scrittura;
  • [ -x "$var" ]: vero se il file esiste e l'utente corrente ha il permesso di esecuzione (o accesso per le directory).

Confronti binari con stringhe contenenti percorsi di file:

  • [ "$var1" -nt "$var2" ]: vero se il file $var1 è più recente di $var2;
  • [ "$var1" -ot "$var2" ]: vero se il file $var1 è più vecchio di $var2;
  • [ "$var1" -et "$var2" ]: vero se i file $var1 e $var2 sono degli hard link allo stesso file;

Con il punto esclamativo ! (NOT) si inverte il senso dei precedenti confronti.

Esecuzione condizionata

Per eseguire un blocco di comandi soltanto se una condizione è soddisfatta si utilizza if, solitamente in combinazione con [...].

La sua sintassi base (in congiunzione con [...]) è:

if [ espressione-booleana ]; then
   ...
[ elif [ espressione-booleana ]; then
   ...               ]  
   ...
[ else ...
   ...               ]
fi

Per esempio:

if [ -z "$var" ]; then
   printf %s\\n "La variabile var è nulla!"
elif [ "$var" = "pluto" ]; then
   printf %s\\n "La variabile var contiene pluto"
else
   printf %s\\n "La variabile var non è nulla e non contiene pluto, ma: ${var}"
fi

Controllo degli errori

Si ricordi che if accetta un comando qualsiasi come condizione, valutandone l'exit status ed eseguendo il ramo then se ha successo, e quello elif/else immediatamente successivo (se presente) altrimenti. Quindi è un ottimo strumento anche per controllare che un comando venga eseguito senza errori, permettendo anche la terminazione immediata dello script:

if comando; then
   printf %s\\n "Comando riuscito!"
else
   printf %s\\n "ERRORE: comando fallito!" >&2  # stampa sullo standard error
   # esci con errore (exit status 1)
   exit 1
fi

E se si è interessati al solo ramo else, basta utilizzare ! prima del comando:

if ! comando; then
   exit 1
fi