Überprüfen, ob mehrere Verzeichnisse vorhanden sind

8

Ich mag für die Existenz von mehreren Verzeichnissen überprüfen, sagen, dir1, dir2und dir3, im Arbeitsverzeichnis.

Ich habe folgendes

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

Aber ich vermute, es gibt einen eleganteren Weg, dies zu tun. Gehen Sie nicht davon aus, dass die Namen der Verzeichnisse ein Muster enthalten.

Ziel ist es, die Existenz einiger Verzeichnisse und die Nichtexistenz anderer zu überprüfen.

Ich verwende Bash, aber tragbarer Code wird bevorzugt.

Eleganz
quelle
1
"Das Ziel ist es, die Existenz einiger Verzeichnisse und die Nichtexistenz anderer zu überprüfen." In Ihrem Beispiel wird geprüft, ob alle aufgelisteten Verzeichnisse vorhanden sind. Können Sie diesen Teil näher erläutern? Ist alles aufgeführt oder aufgeführt? Benötigen Sie eine Überprüfung, ob übergebene Werte tatsächlich Verzeichnisse und keine anderen Dateitypen sind?
Sergiy Kolodyazhnyy
1
Das brauchst du $PWDübrigens nicht. [ -d "$PWD/dir1"]ist äquivalent zu [ -d "dir1" ].
Terdon

Antworten:

5

Wenn Sie bereits erwarten, dass es sich um Verzeichnisse handelt, und nur prüfen, ob sie alle vorhanden sind, können Sie den Exit-Code des lsDienstprogramms verwenden, um festzustellen, ob ein oder mehrere "Fehler" aufgetreten sind :

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

Ich leite die Ausgabe und stderr /dev/nullum, um sie verschwinden zu lassen, da wir uns nur um den Exit-Code von kümmern ls, nicht um dessen Ausgabe. Alles, was geschrieben wurde, /dev/nullverschwindet - es wird nicht in Ihr Terminal geschrieben.

Jeff Schaller
quelle
Können Sie mir helfen, diesen Befehl zu verstehen? Ich weiß, was Dateideskriptoren sind. Ich weiß, 1ist stdout, 2ist stderr und ich weiß, was Umleitung ist. Ich verstehe die Bedeutung von nicht /dev/nullund weiß nicht, wie ich den Befehl analysieren soll.
Eleganz
@Elegance Ich habe eine kleine Erklärung hinzugefügt. Ausführlichere Antworten zu / dev / null finden Sie unter unix.stackexchange.com/questions/163352/… und unix.stackexchange.com/questions/438130/…
Jeff Schaller
Ich versuche immer noch herauszufinden, wie die Syntax funktioniert. Ich habe gelesen, dass &>filenamesowohl stdout als auch stderr an weitergeleitet werden filename. Könnte der Befehl also nicht vereinfacht werden (zumindest für mich ist es einfacher) als ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir2" &>/dev/null && echo All there?
Eleganz
3
(1) Sie sollten wahrscheinlich die -dOption (a) verwenden, um lsnur die Verzeichnisse zu statisieren und nicht zu lesen, und (b) damit der Befehl auch dann erfolgreich ist, wenn der Benutzer keinen Lesezugriff auf die Verzeichnisse hat. (2) Ich sehe keinen Grund, dies zu tun, "$PWD/"außer um mich vor Verzeichnissen zu schützen, deren Namen beginnen -(und natürlich gibt es bessere Möglichkeiten, dies zu tun).
G-Man sagt 'Reinstate Monica'
1
Die Ausführung dieses Befehls kann viel länger dauern als der Test in der ursprünglichen Frage. Außerdem wird nicht nach Verzeichnissen gesucht.
Jasen
9

Ich würde schleifen:

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

Dies führt dazu, breakdass die Schleife kurzgeschlossen wird, genau wie Ihre Kette von&&

Glenn Jackman
quelle
5

Eine Schleife könnte eleganter sein:

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

Das ist Bash. Ein tragbareres ist Sh. Dort können Sie das Positionsarray verwenden:

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

Dann zum Schleifen verwenden "$@".


quelle
5

Warum nicht einfach:

if [ -d "dir1" -a -d "dir2" -a -d "dir3" ]; then
    echo True
else
    echo False
fi
David Conrad
quelle
Dies ist im Wesentlichen das, womit das OP begann,But I suspect there is a more elegant way of doing this
Jeff Schaller
5
Außerdem rät POSIX von der Verwendung von -a: " -aund -obinären Primäroperatoren
Elegance
@ JeffSchaller Es ist knapper, da es alles in einem Aufruf zum Testen erledigt.
David Conrad
2
es ist überhaupt nicht dasselbe, das Original ruft test(aka [) dreimal auf, dies ruft es einmal auf,
Jasen
1
pubs.opengroup.org/onlinepubs/9699919799/utilities/… ist ein genauerer Verweis auf den Speicherort der POSIX-Anweisung.
G-Man sagt "Reinstate Monica"
4

Gemäß der Frage zwei tragbare Shell-Funktionen, die die Existenz und Nichtexistenz mehrerer Verzeichnisse testen:

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

Beispiel:

$ 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
Kusalananda
quelle
1

Ziel ist es, die Existenz einiger Verzeichnisse und  die Nichtexistenz anderer zu überprüfen . [Betonung hinzugefügt]

Aufbauend auf Glenn Jackmans Antwort können wir testen, ob andere Namen wie diese nicht existieren:

Ergebnis = Wahr
für dir in \
        "$ PWD / dir1" \
        "$ PWD / dir2" \
        "$ PWD / dir3" 
tun
    wenn ! [-d "$ dir"]; dann
        Ergebnis = Falsch
        brechen
    fi
erledigt
für dir in \
        "$ PWD / dir4" \
        "$ PWD / dir5" \
        "$ PWD / dir6" 
tun
    if [-e "$ dir"]; dann # Hinweis: nein "!"
        Ergebnis = Falsch
        brechen
    fi
erledigt 
echo "$ result"
Ich habe immer [ -e "$dir" ]getestet, ob es "$dir"existiert. Das heißt, wenn dir5vorhanden, aber eine Datei ist, ist das Ergebnis False. Wenn Sie nur testen möchten, ob die Namen in der zweiten Gruppe Verzeichnisse sind, verwenden Sie [ -d "$dir" ]wie in der ersten Schleife.

Da es darum geht, das Vorhandensein von Dingen im aktuellen Arbeitsverzeichnis zu überprüfen, ist es wahrscheinlich nicht erforderlich, $PWD/die Namen anzugeben . mach einfach

für dir in \
        "dir1" \
        "dir2" \
        "dir3" 
tun
      ︙

G-Man sagt "Reinstate Monica"
quelle