Introduzione

Molte volte durante la scrittura di script Shell, è possibile trovarsi in una situazione in cui è necessario eseguire un'azione in base all'esistenza o meno di un file.

In Bash, è possibile utilizzare il comando test per verificare l'esistenza di un file e determinare il tipo di file.

Il comando test utilizza una delle seguenti forme di sintassi:

test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

Se vuoi che il tuo script sia portatile, dovresti preferire usare il vecchio comando [ test che è disponibile su tutte le shell POSIX. La nuova versione aggiornata del comando test [[ (parentesi doppie) è supportata sulla maggior parte dei sistemi moderni che utilizzano Bash, Zsh e Ksh come shell predefinita.

Controlla se il file esiste

Quando si controlla se esiste un file, gli operatori FILE più comunemente usati sono -e e -f. Il primo verificherà se esiste un file indipendentemente dal tipo, mentre il secondo tornerà vero solo se il FILE è un file normale (non una directory o un dispositivo).

L'opzione più leggibile quando si controlla se esiste o meno un file è utilizzare il comando test in combinazione con l'istruzione if. Gli scripts di seguito verificherà se il file /etc/resolv.conf esiste:

FILE=/etc/resolv.conf
if test -f "$FILE"; then
    echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [[ -f "$FILE" ]]; then
    echo "$FILE exist"
fi

Se si desidera eseguire un'azione diversa in base all'esistenza o meno del file, utilizzare semplicemente il costrutto if/then:

FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exist"
else 
    echo "$FILE does not exist"
fi

Utilizzare sempre virgolette doppie per evitare problemi quando si tratta di file contenenti spazi bianchi nei loro nomi.

È inoltre possibile utilizzare il comando test senza l'istruzione if. Il comando dopo l'operatore && verrà eseguito solo se lo stato di uscita del comando di test è vero,

test -f /etc/resolv.conf && echo "$FILE exist"
[ -f /etc/resolv.conf ] && echo "$FILE exist"
[[ -f /etc/resolv.conf ]] && echo "$FILE exist"

Se si desidera eseguire una serie di comandi dopo che l'operatore && racchiude semplicemente i comandi tra parentesi graffe separate da ; o &&:

[ -f /etc/resolv.conf ] && { echo "$FILE exist"; cp "$FILE" /tmp/; }

Dopo &&, l'istruzione successiva all'operatore || verrà eseguita solo se lo stato di uscita del comando test è false.

[ -f /etc/resolv.conf ] && echo "$FILE exist" || echo "$FILE does not exist"

Controlla se una Directory esiste

Gli operatori -d consentono di verificare se un file è una directory o meno.

Ad esempio, per verificare se esiste la directory /etc/docker dovresti usare:

FILE=/etc/docker
if [ -d "$FILE" ]; then
    echo "$FILE is a directory"
fi
[ -d /etc/docker ] && echo "$FILE is a directory"

Puoi anche usare le doppie parentesi [[ anziché una singola [.

Controlla se il file non esiste

Simile a molte altre lingue, l'espressione di test può essere negata utilizzando l'operatore non logico ! (punto esclamativo):

FILE=/etc/docker
if [ ! -f "$FILE" ]; then
    echo "$FILE does not exist"
fi

Come sopra:

[ ! -f /etc/docker ] && echo "$FILE does not exist"

Controlla se esistono più file

Invece di usare costrutti  nidificati  if/else puoi usare -a (o && con [[) per verificare se esistono più file:

FILE=/etc/docker
if [ -f /etc/resolv.conf -a -f /etc/hosts ]; then
    echo "$FILE is a directory"
fi
FILE=/etc/docker
if [ -f /etc/resolv.conf && -f /etc/hosts ]; then
    echo "$FILE is a directory"
fi

Varianti equivalenti senza usare l'istruzione IF:

[ -f /etc/resolv.conf -a -f /etc/hosts ] && echo "both files exist"
[[ -f /etc/resolv.conf && -f /etc/hosts ]] && echo "both files exist"

Operatori del comando test

Il comando test include i seguenti operatori FILE che consentono di verificare determinati tipi di file:

  • -b FILE - Vero se il FILE esiste ed è un file speciale a blocchi.
  • -c FILE - Vero se il FILE esiste ed è un file di caratteri speciali.
  • -d FILE - Vero se il FILE esiste ed è una directory.
  • -e FILE - Vero se il FILE esiste ed è un file, indipendentemente dal tipo (nodo, directory, socket, ecc.).
  • -f FILE - Vero se il FILE esiste ed è un file normale (non una directory o un dispositivo).
  • -G FILE - Vero se il FILE esiste e ha lo stesso gruppo dell'utente che esegue il comando.
  • -h FILE - Vero se il FILE esiste ed è un collegamento simbolico.
  • -g FILE - Vero se il FILE esiste e ha impostato il flag set-group-id (sgid).
  • -k FILE - Vero se il FILE esiste e ha un flag di sticky bit impostato.
  • -L FILE - Vero se il FILE esiste ed è un collegamento simbolico.
  • -O FILE - Vero se il FILE esiste ed è di proprietà dell'utente che esegue il comando.
  • -p FILE - Vero se il FILE esiste ed è una pipe.
  • -r FILE - Vero se il FILE esiste ed è leggibile.
  • -S FILE - Vero se il FILE esiste ed è socket.
  • -s FILE - Vero se il FILE esiste e ha dimensioni diverse da zero.
  • -u FILE - Vero se il flag esiste e set-user-id (suid) è impostato.
  • -w FILE - Vero se il FILE esiste ed è scrivibile.
  • -x FILE - Vero se il FILE esiste ed è eseguibile.

Conclusione

In questa guida, ti abbiamo mostrato come verificare se esiste un file o una directory usando Bash.