Controlla se esiste una directory in uno script di shell
Domanda
Quale comando può essere utilizzato per verificare se una directory esiste o meno, all'interno di uno script di shell?
Soluzione
Per verificare se esiste una directory in uno script di shell è possibile utilizzare quanto segue:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Oppure per verificare se una directory non esiste:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
Tuttavia, come Jon Ericson sottolinea, i comandi successivi potrebbero non funzionare come previsto se non si tiene conto del fatto che anche un collegamento simbolico a una directory supera questo controllo.Per 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 diversamente, se i comandi successivi prevedono 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
Presta particolare attenzione alle virgolette doppie utilizzate per racchiudere le variabili, la ragione di ciò è spiegata da 8jean in un'altra risposta.
Se le variabili contengono spazi o altri caratteri insoliti, probabilmente lo script fallirà.
Altri suggerimenti
Ricorda di avvolgere sempre le variabili in doppie citazioni quando le fa riferimento in uno script bash.I ragazzi di oggi crescono con l'idea di poter avere spazi e tanti altri personaggi divertenti nei nomi delle loro directory.(Spazi!Ai miei tempi non avevamo spazi fantasiosi!;))
Un giorno, uno di quei ragazzi eseguirà la tua sceneggiatura $DIRECTORY
impostato "My M0viez"
e la tua sceneggiatura esploderà.Non lo vuoi.Quindi usa questo.
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Notare la -D il test 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 è un collegamento simbolico per una directory." Un test leggermente più completo:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
Puoi trovare maggiori informazioni nel manuale di Bash su Espressioni condizionali Bash e il [
comando integrato e il [[
comando composto.
Trovo il doppia parentesi versione di test
rende la scrittura dei test logici più naturale:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
Forma più breve:
[ -d "$DIR" ] && echo "Yes"
Per verificare se esiste una directory puoi usare una semplice struttura if come questa:
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:Fai attenzione, lascia degli spazi vuoti su entrambi i lati dell'apparecchio sia di apertura che di 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
if [ -d "$DIRECTORY" ]; then
# Here if $DIRECTORY exists
fi
Puoi usare test -d
(Vedere man test
).
-d file
Vero se il file esiste ed è una directory.
Per esempio:
test -d "/etc" && echo Exists || echo Does not exist
Nota:IL test
il comando è uguale all'espressione condizionale [
(Vedere: man [
), quindi è portabile tra gli script di shell.
[
- Questo è un sinonimo ditest
builtin, ma l'ultimo argomento deve essere letterale]
, per abbinare l'apertura[
.
Per possibili opzioni o ulteriore aiuto, controlla:
help [
help test
man test
Oman [
Un semplice script per verificare se dir o 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
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 sopra controlleranno che la directory sia presente o meno
$?
se l'ultimo comando ha successo restituisce "0" altrimenti un valore diverso da zero.supponiamotempdir
è già presente alloramkdir tempdir
darà un errore come di seguito:mkdir:impossibile creare la directory "tempdir":il file esiste
O per qualcosa di completamente inutile:
[ -d . ] || echo "No"
Ecco un linguaggio molto pragmatico:
(cd $dir) || return # is this a directory,
# and do we have access?
Di solito 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à già un messaggio standard di una riga a stderr.Fornirà anche più informazioni di quelle che sarò in grado di fornire.Eseguendo il cd
all'interno di una sottoshell ( ... )
, il comando non influisce sulla directory corrente del chiamante.Se la directory esiste, questa subshell e la funzione sono semplicemente un'operazione non operativa.
Il prossimo è l'argomento a cui passiamo cd
: ${1:?pathname expected}
.Questa è una forma più elaborata di sostituzione dei parametri che viene spiegata più dettagliatamente di seguito.
Tl;dr:Se la stringa passata a questa funzione è vuota, usciamo nuovamente dalla subshell ( ... )
e ritorna dalla funzione con il messaggio di errore indicato.
Citando dal ksh93
pagina man:
${parameter:?word}
Se
parameter
è impostato ed è diverso da null, quindi sostituisci il suo valore;altrimenti stampaword
ed esci dalla shell (se non interattiva).Seword
viene omesso, viene stampato un messaggio standard.
E
Se il colon
:
viene omesso dalle espressioni di cui sopra, quindi la shell controlla se il parametro è impostato o meno.
La frase qui è peculiare della documentazione della shell, come word
Può fare riferimento a qualsiasi stringa ragionevole, incluso lo spazio bianco.
In questo caso particolare, so che il messaggio di errore standard 1: parameter not set
non è sufficiente, quindi ingrandisco il tipo di valore che ci aspettiamo qui: the pathname
di una directory.
Una nota filosofica:La shell non è un linguaggio orientato agli oggetti, così dice il messaggio pathname
, non directory
.A questo livello preferirei mantenerlo semplice: gli argomenti di una funzione sono solo stringhe.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
Il codice precedente controlla se la directory esiste e se è scrivibile.
Digita questo codice nel prompt di bash
if [ -d "$DIRECTORY" ]; then
# if true this block of code will execute
fi
Altre funzionalità utilizzando 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 uno schema 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 viene verificata 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
In realtà, dovresti utilizzare diversi strumenti per ottenere un approccio a prova di proiettile:
DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
echo "It's a dir";
fi
Non devi preoccuparti di spazi e caratteri speciali finché li usi "${}"
.
Notare che [[]]
non è portatile come []
, ma poiché la maggior parte delle persone lavora con le versioni moderne di Bash (poiché, dopo tutto, la maggior parte delle persone non lavora nemmeno con la riga di comando :-p), il vantaggio è maggiore del problema.
Per controllare più di una directory utilizzare questo codice:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
Hai considerato di fare semplicemente quello che vuoi fare nel if
piuttosto che guardare prima di saltare?
IE, se vuoi verificare l'esistenza di una directory prima di accedervi, prova semplicemente a fare questo:
if pushd /path/you/want/to/enter; then
# commands you want to run in this directory
popd
fi
Se il percorso a cui dai pushd
esiste, lo inserirai e uscirà con 0
, il che significa che then
parte dell'istruzione verrà eseguita.Se non esiste, non accadrà nulla (a parte qualche output che dice che la directory non esiste, che probabilmente è comunque un effetto collaterale utile per il debug).
Sembra meglio di così, che richiede la ripetizione:
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
, eccetera...se li provi su file che non esistono, usciranno con un errore e stamperanno un messaggio dicendo che non esiste, e il tuo then
il blocco verrà saltato.Se li provi su file che esistono, il comando verrà eseguito e uscirà con lo stato di 0
, consentendo al tuo then
blocco da eseguire.
Controlla se la directory esiste, altrimenti creane una
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
NB:Citare le variabili è una buona pratica.
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Questa risposta racchiuso come uno script di shell
Esempi
$ is_dir ~
YES
$ is_dir /tmp
YES
$ is_dir ~/bin
YES
$ mkdir '/tmp/test me'
$ is_dir '/tmp/test me'
YES
$ is_dir /asdf/asdf
NO
# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
echo "Folder doesnt exist: $DIR";
exit;
fi
is_dir
function show_help()
{
IT=$(CAT <<EOF
usage: DIR
output: YES or NO, depending on whether or not the directory exists.
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
DIR=$1
if [ -d $DIR ]; then
echo "YES";
exit;
fi
echo "NO";
Usando il -e
check controllerà la presenza di file e questo include le directory.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
Come da Jonathan commento:
Se vuoi creare la directory e questa non esiste ancora, la tecnica più semplice è usare mkdir -p
che crea la directory - e tutte le directory mancanti nel percorso - e non fallisce se la directory esiste già, quindi puoi farlo tutto in una volta con:
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
Questo non è del tutto vero...Se vuoi andare in quella directory, devi anche avere i diritti di esecuzione sulla directory.Forse devi avere anche i diritti di scrittura.
Pertanto:
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
IL ls
comando insieme a -l
(elenco lungo) l'opzione restituisce informazioni sugli attributi su file e directory.
In particolare il primo carattere di ls -l
l'output è solitamente a d
o a -
(trattino).Nel caso di a d
quella elencata è sicuramente una directory.
Il seguente comando in una sola riga ti dirà se il dato ISDIR
la variabile contiene o meno il percorso di una directory:
[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
Utilizzo pratico:
[claudio@nowhere ~]$ ISDIR="$HOME/Music"
[claudio@nowhere ~]$ ls -ld "$ISDIR"
drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
[claudio@nowhere ~]$ [[ $(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.
[claudio@nowhere ~]$ touch "empty file.txt"
[claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt"
[claudio@nowhere ~]$ [[ $(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
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
Se vuoi verificare se esiste una directory, indipendentemente dal fatto che sia una directory reale o un collegamento simbolico, usa 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 l'errore "ls:/X:No such file or directory" se la directory o il collegamento simbolico non esiste e imposta anche il codice di ritorno, che puoi recuperare tramite "$?", su un valore diverso da zero (normalmente "1").Assicurati di controllare il codice di ritorno subito dopo aver chiamato "ls".
(1)
[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"
(2)
[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"
(3)
[[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists"
Se viene riscontrato un problema con uno degli approcci sopra indicati.
Con ls
comando;nei casi in cui la directory non esiste: viene visualizzato un messaggio di errore
$ [[ ls -ld SAMPLE_DIR| grep ^d | wc -l
-eq 1]] && echo esiste || non esiste -ksh:non:non trovato [Nessun file o directory di questo tipo]
Ottime soluzioni disponibili, ma alla fine ogni script fallirà se non ti trovi nella directory giusta.Quindi codice come questo:
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
verrà eseguito con successo solo se al momento dell'esecuzione ti trovi in una directory che ha una sottodirectory che ti capita di controllare.
Capisco la domanda iniziale in questo modo:per verificare se una directory esiste indipendentemente dalla posizione dell'utente nel file system.Quindi usare il comando "trova" potrebbe risolvere il problema:
dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d
Questa soluzione è buona perché consente l'uso dei caratteri jolly, una funzionalità utile durante la ricerca di file/directory.L'unico problema è che, se la directory cercata non esiste, il comando 'find' non stamperà nulla sullo stdout (non è una soluzione elegante per i miei gusti) e avrà comunque un'uscita zero.Forse qualcuno potrebbe migliorare in questo.
Di seguito è possibile utilizzare la ricerca,
find . -type d -name dirname -prune -print