Vérification de l'existence de plusieurs répertoires


8

Je souhaite vérifier l'existence de plusieurs répertoires, par exemple dir1, dir2et dir3dans le répertoire de travail.

J'ai le suivant

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

Mais je soupçonne qu'il existe une façon plus élégante de procéder. Ne présumez pas qu'il existe un modèle dans les noms des répertoires.

Le but est de vérifier l'existence de quelques répertoires et la non-existence d'autres.

J'utilise Bash, mais le code portable est préférable.


1
"Le but est de vérifier l'existence de quelques répertoires et la non-existence d'autres". Eh bien, votre exemple vérifie l'existence de tous les répertoires répertoriés. Pouvez-vous élaborer sur cette partie? Est-ce que tout est répertorié ou tout répertorié? Avez-vous besoin d'une vérification que les valeurs transmises sont en fait des répertoires et non d'autres types de fichiers?
Sergiy Kolodyazhnyy

1
Au fait, vous n'avez pas besoin de ça $PWD. [ -d "$PWD/dir1"]est équivalent à [ -d "dir1" ].
terdon

Réponses:


5

Si vous vous attendez déjà à ce qu'ils soient des répertoires et que vous vérifiez simplement s'ils existent tous, vous pouvez utiliser le code de sortie de l' lsutilitaire pour déterminer si une ou plusieurs "erreurs se sont produites" :

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

Je redirige la sortie et stderr vers /dev/nullafin de le faire disparaître, car nous nous soucions uniquement du code de sortie de ls, pas de sa sortie. Tout ce qui est écrit /dev/nulldisparaît - il n'est pas écrit sur votre terminal.


Pouvez-vous m'aider à comprendre cette commande? Je connais les descripteurs de fichiers. Je sais que 1c'est stdout, 2est stderr et je sais ce qu'est la redirection. Je ne comprends pas la signification de /dev/null, et je ne sais pas comment analyser la commande.
Elegance

@Elegance J'ai ajouté une petite explication. Pour des réponses plus approfondies concernant / dev / null, voir unix.stackexchange.com/questions/163352/… et unix.stackexchange.com/questions/438130/…
Jeff Schaller

J'essaie toujours de comprendre comment fonctionne la syntaxe. J'ai lu que &>filenameredirige à la fois stdout et stderr vers filename. Donc, la commande ne pourrait-elle pas être simplifiée (du moins pour moi, c'est plus simple) ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir2" &>/dev/null && echo All there?
Elegance

3
(1) Vous devriez probablement utiliser l' -doption (a) donc lsil suffit de statuer les répertoires, et non de les lire, et (b) pour que la commande réussisse même si l'utilisateur n'a pas accès en lecture aux répertoires. (2) Je ne vois aucune raison d'utiliser, "$PWD/"sauf pour se prémunir contre les répertoires dont les noms commencent par -(et, bien sûr, il existe de meilleures façons de le faire).
G-Man dit `` Réintègre Monica ''

1
l'exécution de cette commande peut prendre beaucoup plus de temps que le test de la question d'origine. il ne vérifie pas non plus les répertoires.
Jasen

9

Je boucle:

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

La breakprovoque un court-circuit de la boucle, tout comme votre chaîne de&&


5

Une boucle pourrait être plus élégante:

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

C'est Bash. Un plus portable est Sh. Là, vous pouvez utiliser le tableau de position:

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

Ensuite, pour boucler dessus, utilisez "$@".


5

Pourquoi pas seulement:

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

C'est essentiellement ce avec quoi l'OP a commencé,But I suspect there is a more elegant way of doing this
Jeff Schaller

5
POSIX décourage également l'utilisation de -a: " -aet -oles opérateurs primaires binaires (...) ont été marqués comme obsolètes": pubs.opengroup.org/onlinepubs/9699919799
Elegance

@JeffSchaller C'est plus concis car il fait tout en un seul appel pour tester.
David Conrad

2
ce n'est pas du tout pareil, l'original invoque test(aka [) trois fois ceci l'invoque une fois,
Jasen

1
pubs.opengroup.org/onlinepubs/9699919799/utilities/… est une référence plus précise à l'emplacement de l'instruction POSIX.
G-Man dit `` Réintègre Monica ''

4

Selon la question, deux fonctions shell portables qui testent l'existence et la non-existence de plusieurs répertoires:

# 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
}

Exemple:

$ 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

Le but est de vérifier l'existence de quelques répertoires et la non-existence d'autres.   [Italiques ajoutés]

En nous appuyant sur la réponse de Glenn Jackman , nous pouvons tester la non-existence d'autres noms comme celui-ci:

result = True
pour dir dans \
        "$ PWD / dir1" \
        "$ PWD / dir2" \
        "$ PWD / dir3" 
faire
    si ! [-d "$ dir"]; puis
        result = False
        Pause
    Fi
terminé
pour dir dans \
        "$ PWD / dir4" \
        "$ PWD / dir5" \
        "$ PWD / dir6" 
faire
    if [-e "$ dir"]; alors # Remarque: pas de "!"
        result = False
        Pause
    Fi
fait 
écho "$ result"
J'avais l'habitude [ -e "$dir" ]de tester s'il "$dir"existe; c'est-à-dire, s'il dir5existe mais est un fichier, le résultat est False. Si vous voulez seulement tester si les noms du deuxième groupe sont des répertoires, utilisez [ -d "$dir" ], comme dans la première boucle.

Puisque nous parlons de vérifier l'existence de choses dans le répertoire de travail actuel, il n'est probablement pas nécessaire de spécifier $PWD/les noms; fais juste

pour dir dans \
        "dir1" \
        "dir2" \
        "dir3" 
faire
      ︙

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.