Verifica dell'esistenza di più directory


8

Voglio verificare l'esistenza di più directory, per esempio dir1, dir2e dir3, nella directory di lavoro.

Ho il seguente

if [ -d "$PWD/dir1" ] && [ -d "$PWD/dir2" ] && [ -d "$PWD/dir3" ]; then
    echo True
else
    echo False
fi

Ma sospetto che ci sia un modo più elegante di farlo. Non dare per scontato che esista uno schema nei nomi delle directory.

L'obiettivo è verificare l'esistenza di alcune directory e l'assenza di altre.

Sto usando Bash, ma è preferito il codice portatile.


1
"L'obiettivo è verificare l'esistenza di alcune directory e la inesistenza di altre". Bene, il tuo esempio controlla l'esistenza di tutte le directory elencate. Puoi approfondire questa parte? È tutto elencato o elencato? È necessario verificare che i valori passati siano in realtà directory e non altri tipi di file?
Sergiy Kolodyazhnyy

1
A $PWDproposito, non ti serve . [ -d "$PWD/dir1"]è equivalente a [ -d "dir1" ].
terdon

Risposte:


5

Se ti aspetti già che siano directory e stai solo verificando se esistono tutte, puoi utilizzare il codice di uscita lsdall'utilità per determinare se uno o più "errori" si sono verificati :

ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir3" >/dev/null 2>&1 && echo All there

Reindirizzo l'output e stderr su /dev/nullper farlo scomparire, poiché ci preoccupiamo solo del codice di uscita ls, non del suo output. Tutto ciò su cui è scritto /dev/nullscompare - non è scritto sul tuo terminale.


Potete aiutarmi a capire questo comando? So quali sono i descrittori di file. So che 1è stdout, 2è stderr e so cos'è il reindirizzamento. Non capisco il significato di /dev/null, e non so come analizzare il comando.
Elegance

@Elegance ho aggiunto una piccola spiegazione. Per risposte più approfondite su / dev / null, vedere unix.stackexchange.com/questions/163352/… e unix.stackexchange.com/questions/438130/…
Jeff Schaller

Sto ancora cercando di capire come funziona la sintassi. Ho letto che &>filenamereindirizza sia stdout che stderr a filename. Quindi il comando non potrebbe essere semplificato (almeno per me è più semplice) come ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir2" &>/dev/null && echo All there?
Elegance

3
(1) Probabilmente dovresti usare l' -dopzione (a), quindi devi lssolo stat le directory e non leggerle, e (b) quindi il comando avrà successo anche se l'utente non ha accesso in lettura alle directory. (2) Non vedo alcun motivo per usare "$PWD/"se non quello di guardarmi dalle directory i cui nomi iniziano con -(e, ovviamente, ci sono modi migliori per farlo).
G-Man dice "Ripristina Monica" il

1
l'esecuzione di questo comando potrebbe richiedere molto più tempo del test nella domanda originale. inoltre non controlla le directory.
Jasen

9

Vorrei loop:

result=True
for dir in \
        "$PWD/dir1" \
        "$PWD/dir2" \
        "$PWD/dir3" 
do
    if ! [ -d "$dir" ]; then
        result=False
        break
    fi
done
echo "$result"

Ciò breakcausa il corto circuito del loop, proprio come la tua catena di&&


5

Un loop potrebbe essere più elegante:

arr=("$PWD/dir1" "$PWD/dir2" "$PWD/dir2")
for d in "${arr[@]}"; do
    if [ -d "$d"]; then
        echo True
    else
        echo False
    fi
done

Questo è Bash. Uno più portatile è Sh. Lì puoi usare l'array posizionale:

set -- "$PWD/dir1" "$PWD/dir2" "$PWD/dir2"

Quindi passarci sopra usando "$@".


5

Perché non solo:

if [ -d "dir1" -a -d "dir2" -a -d "dir3" ]; then
    echo True
else
    echo False
fi

Questo è essenzialmente ciò con cui è iniziato l'OP,But I suspect there is a more elegant way of doing this
Jeff Schaller

5
Inoltre POSIX scoraggia l'uso di -a: " -ae gli -ooperatori binari delle primarie (...) sono stati contrassegnati come obsoleti": pubs.opengroup.org/onlinepubs/9699919799
Elegance

@JeffSchaller È più conciso poiché fa tutto in una chiamata per testare.
David Conrad

2
non è affatto lo stesso, l'originale invoca test(aka [) tre volte questo lo invoca una volta,
Jasen


4

Secondo la domanda, due funzioni di shell portatili che verificano l'esistenza e l'inesistenza di più directory:

# Returns success if all given arguments exists and are directories.
ck_dir_exists () {
    for dir do
        [ -d "$dir" ] || return 1
    done
}

# Returns success if none of the given arguments are existing directories.
ck_dir_notexists () {
    for dir do
        [ ! -d "$dir" ] || return 1
    done
}

Esempio:

$ mkdir dir1 dir2
$ ck_dir_exists dir1 dir2; echo $?
0
$ ck_dir_exists dir1 dir2 dir3; echo $?
1
$ ck_dir_notexists dir1 dir2 dir3; echo $?
1
$ ck_dir_notexists dir3 dir4; echo $?
0

1

L'obiettivo è verificare l'esistenza di alcune directory e l'assenza di altre.   [Enfasi aggiunta]

Sulla risposta di Glenn Jackman , siamo in grado di verificare l'esistenza di altri nomi come questo:

risultato = True
per dir in \
        "$ PWD / dir1" \
        "$ PWD / dir2" \
        "$ PWD / dir3" 
fare
    Se ! [-d "$ dir"]; poi
        risultato = False
        rompere
    fi
fatto
per dir in \
        "$ PWD / dir4" \
        "$ PWD / dir5" \
        "$ PWD / dir6" 
fare
    if [-e "$ dir"]; quindi # Nota: nessun “!”
        risultato = False
        rompere
    fi
done 
echo "$ risultato"
Ero solito [ -e "$dir" ]verificare se "$dir"esiste; cioè, se dir5esiste ma è un file, il risultato è False. Se vuoi solo verificare se i nomi nel secondo gruppo sono directory, usa [ -d "$dir" ], come nel primo ciclo.

Dato che stiamo parlando del controllo dell'esistenza di cose nella directory di lavoro corrente, probabilmente non è necessario specificare $PWD/i nomi; basta fare

per dir in \
        "dir1" \
        "dir2" \
        "Dir3" 
fare
      ︙

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.