test - Controlla se esiste una directory in uno script di shell




operatori bash linux (20)

Quale comando può essere usato per verificare se una directory esiste o no, all'interno di uno script di shell?


Altre funzioni che utilizzano find

  • Verifica l'esistenza della cartella all'interno delle sottodirectory:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
    
  • Verifica l'esistenza di una o più cartelle in base a un modello all'interno della directory corrente:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
    
  • Entrambe le combinazioni Nell'esempio seguente, controlla l'esistenza della cartella nella directory corrente:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi
    

  1. Un semplice script per verificare se la directory o il file è presente o meno:

    if [ -d /home/ram/dir ]   # for file "if [-f /home/rama/file]" 
    then 
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. Un semplice script per verificare se la directory è presente o meno:

    mkdir tempdir   # if you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    

    Gli script di cui sopra controlleranno che la directory sia presente o meno

    $? se l'ultimo comando lo esegue, restituisce "0" altro valore diverso da zero. supponiamo che tempdir sia già presente quindi mkdir tempdir darà errore come di seguito:

    mkdir: impossibile creare la directory 'tempdir': il file esiste


Come da commento :

Se vuoi creare la directory e non esiste ancora, la tecnica più semplice è usare mkdir -p che crea la directory - e qualsiasi directory mancante sul percorso - e non fallisce se la directory esiste già, quindi puoi fai tutto in una volta con:

mkdir -p /some/directory/you/want/to/exist || exit 1

Controlla se la directory esiste, altrimenti creane una

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY

Ecco un idioma molto pragmatico:

(cd $dir) || return # is this a directory,
                    # and do we have access?

In genere lo avvolgo in una funzione:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

O:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

La cosa bella di questo approccio è che non devo pensare a un buon messaggio di errore.

cd mi darà un messaggio standard a una riga per stderr già. Fornirà inoltre più informazioni di quelle che potrò fornire. Eseguendo il cd all'interno di una subshell ( ... ) , il comando non ha alcun effetto sulla directory corrente del chiamante. Se la directory esiste, questa subshell e la funzione sono solo un no-op.

Il prossimo argomento è che passiamo a cd : ${1:?pathname expected} . Questa è una forma più elaborata di sostituzione dei parametri che è spiegata in maggior dettaglio di seguito.

Tl; dr: Se la stringa passata in questa funzione è vuota, usciamo nuovamente dalla subshell ( ... ) e torniamo dalla funzione con il messaggio di errore fornito.

Citando dalla pagina man ksh93 :

${parameter:?word}

Se il parameter è impostato e non è nullo, sostituire il suo valore; altrimenti, stampa la word e esce dalla shell (se non interattiva). Se la word viene omessa, viene stampato un messaggio standard.

e

Se i due punti : viene omesso dalle espressioni di cui sopra, la shell controlla solo se il parametro è impostato o meno.

Il fraseggio qui è peculiare alla documentazione della shell, poiché la word può riferirsi a qualsiasi stringa ragionevole, compresi gli spazi bianchi.

In questo caso particolare, so che il messaggio di errore standard 1: parameter not set è sufficiente, quindi eseguo l'ingrandimento del tipo di valore che ci aspettiamo qui: il pathname di pathname di una directory.

Una nota filosofica: la shell non è un linguaggio orientato agli oggetti, quindi il messaggio dice pathname , non directory . A questo livello, preferirei mantenerlo semplice: gli argomenti di una funzione sono solo stringhe.


Forma più breve:

[ -d "$DIR" ] && echo "Yes"

Hai preso in considerazione solo quello che vuoi fare nel if invece di guardare prima di saltare?

IE, se vuoi verificare l'esistenza di una directory prima di inserirla, prova a fare questo:

if pushd /path/you/want/to/enter; then
    # commands you want to run in this directory
    popd
fi

Se il percorso che pushd a pushd esiste, lo inserirai e pushd con 0 , il che significa che la parte pushd verrà eseguita. Se non esiste, non accadrà nulla (a parte qualche output che dice che la directory non esiste, che è probabilmente un utile effetto collaterale comunque per il debug).

Sembra meglio di questo, che richiede di ripetere te stesso:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # commands you want to run in this directory
    popd
fi

La stessa cosa funziona con cd , mv , rm , ecc ... se li provi su file che non esistono, usciranno con un errore e stamperanno un messaggio che dice che non esiste, e il tuo blocco then sarà saltato. Se li provi su file esistenti, il comando verrà eseguito ed uscirà con lo stato 0 , consentendo l'esecuzione del blocco.


Il comando ls in combinazione con -l opzione -l (long listing) restituisce le informazioni sugli attributi di file e directory.
In particolare il primo carattere di ls -l output è solitamente un d o un - (trattino). In caso di una di quelle elencate è sicuramente una directory.

Il seguente comando in una riga ti dirà se la variabile ISDIR fornita contiene un percorso verso una directory o meno:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

Uso pratico:

    [[email protected] ~]$ ISDIR="$HOME/Music" 
    [[email protected] ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [[email protected] ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [[email protected] ~]$ touch "empty file.txt"
    [[email protected] ~]$ ISDIR="$HOME/empty file.txt" 
    [[email protected] ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory

Nota che il test -d può produrre alcuni risultati sorprendenti:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

File sotto: "Quando una directory non è una directory?" La risposta: "Quando si tratta di un collegamento simbolico a una directory". Un test leggermente più approfondito:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

Puoi trovare maggiori informazioni nel manuale di Bash sulle espressioni condizionali di Bash e il [ comando incorporato e [[ comando composto .


O per qualcosa di completamente inutile:

[ -d . ] || echo "No"

Per verificare se esiste una directory in uno script di shell puoi usare quanto segue:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

O per verificare se una directory non esiste:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

Tuttavia, come sottolinea Jon Ericson , i comandi successivi potrebbero non funzionare come previsto se non si tiene conto del fatto che un collegamento simbolico a una directory supererà anche questo controllo. Ad esempio, eseguendo questo:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Produrrà il messaggio di errore:

rmdir: failed to remove `symlink': Not a directory

Quindi i collegamenti simbolici potrebbero dover essere trattati in modo diverso, se i comandi successivi si aspettano le directory:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

Prendete nota delle doppie virgolette usate per avvolgere le variabili, la ragione di ciò è spiegata da 8jean in un'altra risposta .

Se le variabili contengono spazi o altri caratteri insoliti, probabilmente causerà il fallimento dello script.


Per verificare se esiste una directory puoi usare la struttura semplice se così:

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

Puoi farlo anche in negativo

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

Nota : fare attenzione, lasciare spazi vuoti su entrambi i lati delle bretelle di apertura e chiusura.

Con la stessa sintassi puoi usare:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 

Ricordarsi di avvolgere sempre le variabili tra virgolette quando le si fa riferimento in uno script bash. I bambini di questi tempi crescono con l'idea che possano avere spazi e molti altri personaggi divertenti nei loro nomi di directory. (Spazi! Ai miei tempi, non avevamo spazi fantastici!;))

Un giorno, uno di quei ragazzi eseguirà il tuo script con $DIRECTORY impostato su "My M0viez" e il tuo script esploderà. Tu non vuoi quello. Quindi usa questo.

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

Se si desidera verificare se esiste una directory, indipendentemente dal fatto che si tratti di una directory reale o di un collegamento simbolico, utilizzare questo:

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

Spiegazione: Il comando "ls" restituisce un errore "ls: / x: nessun file o directory" se la directory o il collegamento simbolico non esiste e imposta anche il codice di ritorno, che è possibile recuperare tramite "$?", Su non -null (normalmente "1"). Assicurati di controllare il codice di ritorno direttamente dopo aver chiamato "ls".



Usando l' -e controllerà i file e questo include le directory.

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"

[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

NB: la citazione di variabili è una buona pratica.


if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

Questo non è completamente vero ... Se vuoi andare in quella directory, devi anche avere i diritti di esecuzione sulla directory. Forse hai anche bisogno di avere diritti di scrittura.

therfore:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi




posix