Mit welchem Befehl kann überprüft werden, ob in einem Bash-Shell-Skript ein Verzeichnis vorhanden ist oder nicht?
Um zu überprüfen, ob ein Verzeichnis in einem Shell-Skript vorhanden ist, können Sie Folgendes verwenden:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Oder um zu überprüfen, ob kein Verzeichnis vorhanden ist:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
Wie Jon Ericson jedoch betont, funktionieren nachfolgende Befehle möglicherweise nicht wie beabsichtigt, wenn Sie nicht berücksichtigen, dass eine symbolische Verknüpfung zu einem Verzeichnis diese Prüfung ebenfalls besteht. ZB laufen lassen:
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
Wird die Fehlermeldung erzeugen:
rmdir: failed to remove `symlink': Not a directory
Daher müssen symbolische Links möglicherweise anders behandelt werden, wenn nachfolgende Befehle Verzeichnisse erwarten:
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
Beachten Sie insbesondere die doppelten Anführungszeichen, mit denen die Variablen umbrochen werden. Der Grund dafür wird von 8jean in einer anderen Antwort erklärt .
Wenn die Variablen Leerzeichen oder andere ungewöhnliche Zeichen enthalten, schlägt das Skript wahrscheinlich fehl.
--
dringend empfohlen (End-of-Options-Marker). Andernfalls schlägt das Skript wie bei Leerzeichen fehl, wenn Ihre Variable etwas enthält, das wie eine Option aussieht.[ ! -d "$DIRECTORY" ]
Wird wahr sein, wenn$DIRECTORY
sie nicht existiert oder wenn sie existiert, aber kein Verzeichnis ist. Betrachten Sie etwas wieif [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; Dies schlägt fehl, wenn"$DIRECTORY"
es sich um eine Datei handelt. (Natürlich sollten Sie prüfen, obmkdir
es trotzdem gelungen ist; es gibt eine Reihe von Gründen, warum dies fehlschlagen kann.)-d
) als auch nach dem Symlink (-L
) zu testen , ist es einfacher, einfach einen Schrägstrich an die Variable anzuhängen, wie zif [ -d "${THING:+$THING/}" ]
. Ein Verzeichnis hat nichts gegen den zusätzlichen Schrägstrich. Eine Datei wird als falsch ausgewertet. Leer bleibt leer, also falsch. Und ein Symlink wird zu seinem Ziel aufgelöst. Natürlich hängt es von Ihrem Ziel ab. Wenn Sie wollen , gehen Sie dort, das ist in Ordnung. Wenn Sie es löschen möchten , ist der Code in dieser Antwort besser.Denken Sie daran, Variablen immer in doppelte Anführungszeichen zu setzen, wenn Sie in einem Bash-Skript auf sie verweisen. Kinder wachsen heutzutage mit der Idee auf, dass sie Leerzeichen und viele andere lustige Charaktere in ihren Verzeichnisnamen haben können. (Räume! Damals hatten wir keine ausgefallenen Räume !;))
Eines Tages wird eines dieser Kinder Ihr Skript mit
$DIRECTORY
set to ausführen"My M0viez"
und Ihr Skript wird explodieren. Das willst du nicht. Also benutze das.quelle
Beachten Sie, dass der -d- Test einige überraschende Ergebnisse liefern kann:
Datei unter: "Wann ist ein Verzeichnis kein Verzeichnis?" Die Antwort: "Wenn es sich um einen Symlink zu einem Verzeichnis handelt." Ein etwas gründlicherer Test:
Weitere Informationen finden Sie im Bash-Handbuch zu Bash-Bedingungsausdrücken sowie im
[
eingebauten Befehl und im[[
zusammengesetzten Befehl .quelle
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... oder für einen Befehl, der sowohl für Links als auch für Verzeichnisse funktioniert:rm -r tmpdir
Ich finde, dass die Doppelklammerversion von
test
das Schreiben von Logiktests natürlicher macht:quelle
if [[ -d "$TARFILE" ]]
ich bekomme [[: nicht gefunden[[ ]]
unterstützt, bietet aber tatsächlich keine andere Funktionalität als[ ]
. Wenn die Portabilität ein Problem darstellt, halten Sie sich an[ ]
die erforderlichen Problemumgehungen und verwenden Sie diese.Kürzere Form:
quelle
if $dir is a dir, then echo "yes"
? Ein bisschen Erklärung würde helfen :)cmd && other
ist eine gebräuchliche Abkürzung fürif cmd; then other; fi
- dies funktioniert mit den meisten Programmiersprachen, die die Boolesche Logik unterstützen, und wird als Kurzschlussauswertung bezeichnet .set -e
(dies ist eine bewährte Methode für die Shell-Programmierung ).[ -d "$DIR" ]
wird überprüft (gefolgt von&& echo Yes
), daher glaube ich,set -e
dass es keinen Unterschied zum Skriptverhalten macht (dh wenn der Test fehlschlägt, wird das Skript normal fortgesetzt).Um zu überprüfen, ob ein Verzeichnis vorhanden ist, können Sie eine einfache
if
Struktur wie die folgende verwenden:Sie können es auch negativ machen:
Hinweis : Seien Sie vorsichtig. Lassen Sie auf beiden Seiten der öffnenden und schließenden Klammern leere Stellen.
Mit der gleichen Syntax können Sie verwenden:
quelle
Ein einfaches Skript zum Testen, ob ein Verzeichnis oder eine Datei vorhanden ist oder nicht:
Ein einfaches Skript, um zu überprüfen, ob das Verzeichnis vorhanden ist oder nicht:
Die obigen Skripte prüfen, ob das Verzeichnis vorhanden ist oder nicht
$?
Wenn der letzte Befehl erfolgreich ist, wird "0" zurückgegeben, andernfalls ein Wert ungleich Null. Angenommen, estempdir
ist bereits vorhanden. Dannmkdir tempdir
wird ein Fehler wie folgt ausgegeben:quelle
Sie können verwenden
test -d
(sieheman test
).Zum Beispiel:
Hinweis: Der
test
Befehl entspricht dem bedingten Ausdruck[
(siehe :)man [
, ist also für Shell-Skripte portierbar.Weitere Optionen oder weitere Hilfe finden Sie unter:
help [
help test
man test
oderman [
quelle
Oder für etwas völlig Nutzloses:
quelle
Hier ist eine sehr pragmatische Redewendung:
Normalerweise verpacke ich es in eine Funktion:
Oder:
Das Schöne an diesem Ansatz ist, dass mir keine gute Fehlermeldung einfällt.
cd
Ich erhalte bereits eine einzeilige Standardnachricht zum Standardfehler . Es wird auch mehr Informationen geben, als ich liefern kann. Durch das Ausführencd
einer Unterschale wirkt( ... )
sich der Befehl nicht auf das aktuelle Verzeichnis des Aufrufers aus. Wenn das Verzeichnis vorhanden ist, sind diese Unterschale und die Funktion nur ein No-Op.Als nächstes kommt das Argument, an das wir übergeben
cd
:${1:?pathname expected}
. Dies ist eine ausführlichere Form der Parametersubstitution, die im Folgenden näher erläutert wird.Tl; dr: Wenn die an diese Funktion übergebene Zeichenfolge leer ist, verlassen wir die Unterschale erneut
( ... )
und kehren mit der angegebenen Fehlermeldung von der Funktion zurück.Zitat aus der
ksh93
Manpage:und
Die Formulierung hier ist der Shell-Dokumentation eigen, da
word
sie sich auf jede vernünftige Zeichenfolge beziehen kann, einschließlich Leerzeichen.In diesem speziellen Fall weiß ich, dass die Standardfehlermeldung
1: parameter not set
nicht ausreicht, daher vergrößere ich den Wertetyp, den wir hier erwarten - denpathname
eines Verzeichnisses.Eine philosophische Anmerkung:
Die Shell ist keine objektorientierte Sprache, daher heißt es in der Nachricht
pathname
nichtdirectory
. Auf dieser Ebene möchte ich es lieber einfach halten - die Argumente für eine Funktion sind nur Zeichenfolgen.quelle
test -d
wie @Grundlefleck erklärt.test -d /unreadable/exists
wird fehlschlagen, auch wenn das Argument existiert.Der obige Code prüft, ob das Verzeichnis vorhanden und beschreibbar ist.
quelle
Versuchen Sie es online
quelle
space
nach[
-> [`` -d . Ich habe einen Fehler wegen fehlenden Platzes bekommenGeben Sie diesen Code an der Bash-Eingabeaufforderung ein:
quelle
Weitere Funktionen mit
find
Überprüfen Sie die Existenz des Ordners in Unterverzeichnissen:
Überprüfen Sie die Existenz eines oder mehrerer Ordner anhand eines Musters im aktuellen Verzeichnis:
Beide Kombinationen. Im folgenden Beispiel wird die Existenz des Ordners im aktuellen Verzeichnis überprüft:
quelle
find -maxdepth 1 -type d -name 'pattern'
. Stört es Sie, wenn ich in Ihrer Antwort diesen Trick anhänge? Prost;)Eigentlich sollten Sie mehrere Tools verwenden, um einen kugelsicheren Ansatz zu erhalten:
Sie müssen sich keine Gedanken über Leerzeichen und Sonderzeichen machen, solange Sie diese verwenden
"${}"
.Beachten Sie, dass dies
[[]]
nicht so portabel ist wie[]
, aber da die meisten Leute mit modernen Versionen von Bash arbeiten (da die meisten Leute schließlich nicht einmal mit der Befehlszeile arbeiten :-p), ist der Nutzen größer als der Ärger.quelle
Haben Sie darüber nachgedacht, einfach das zu tun, was Sie wollen,
if
anstatt zu schauen, bevor Sie springen?Wenn Sie also vor dem Betreten überprüfen möchten, ob ein Verzeichnis vorhanden ist, versuchen Sie Folgendes:
Wenn der Pfad, den Sie angeben,
pushd
vorhanden ist, geben Sie ihn ein und er wird mit beendet0
, was bedeutet, dass derthen
Teil der Anweisung ausgeführt wird. Wenn es nicht existiert, passiert nichts (außer einer Ausgabe, die besagt, dass das Verzeichnis nicht existiert, was wahrscheinlich sowieso ein hilfreicher Nebeneffekt beim Debuggen ist).Es scheint besser als das, was erfordert, dass Sie sich wiederholen:
Dasselbe funktioniert mit
cd
,mv
,rm
, etc ... , wenn man sie auf Dateien versuchen, die nicht existieren, werden sie mit einem Fehler beenden und eine Meldung aus sagen , dass es nicht vorhanden ist , und Ihrthen
Block wird übersprungen. Wenn Sie sie an vorhandenen Dateien ausprobieren, wird der Befehl ausgeführt und mit dem Status "0
Beendet", sodass Ihrthen
Block ausgeführt werden kann.quelle
Verwenden Sie diesen Code, um mehr als ein Verzeichnis zu überprüfen:
quelle
Überprüfen Sie, ob das Verzeichnis vorhanden ist, andernfalls erstellen Sie eines:
quelle
mkdir -p "$DIRECTORY"
für den gleichen Effekt verwenden.Erläuterung:
-d
: Überprüfen Sie, ob es sich um ein Verzeichnis handelt-L
: Überprüfen Sie, ob es sich um einen symbolischen Link handeltquelle
quelle
Diese Antwort wurde als Shell-Skript zusammengefasst
Beispiele
is_dir
quelle
Mit der
-e
Prüfung wird nach Dateien gesucht, einschließlich Verzeichnissen.quelle
Gemäß Jonathans Kommentar:
Wenn Sie das Verzeichnis erstellen möchten und es noch nicht vorhanden ist, verwenden Sie am einfachsten
mkdir -p
das Verzeichnis - und alle fehlenden Verzeichnisse im Pfad - und schlagen nicht fehl, wenn das Verzeichnis bereits vorhanden ist, sodass Sie alles tun können sofort mit:quelle
Das ist nicht ganz richtig ...
Wenn Sie in dieses Verzeichnis wechseln möchten, müssen Sie auch über die Ausführungsrechte für das Verzeichnis verfügen. Möglicherweise müssen Sie auch Schreibrechte haben.
Deshalb:
quelle
Verwenden Sie das
file
Programm. Da alle Verzeichnisse auch Dateien unter Linux sind, würde die Ausgabe des folgenden Befehls ausreichen:file $directory_name
Überprüfen einer nicht vorhandenen Datei:
file blah
Ausgabe:
cannot open 'blah' (No such file or directory)
Überprüfen eines vorhandenen Verzeichnisses:
file bluh
Ausgabe:
bluh: directory
quelle
Der
ls
Befehl in Verbindung mit der-l
Option (lange Auflistung) gibt Attributinformationen zu Dateien und Verzeichnissen zurück.Insbesondere das erste Zeichen der
ls -l
Ausgabe ist normalerweise eind
oder ein-
(Bindestrich). Im Falle eines istd
das aufgelistete sicher ein Verzeichnis.Der folgende Befehl in nur einer Zeile zeigt an, ob die angegebene
ISDIR
Variable einen Pfad zu einem Verzeichnis enthält oder nicht:Praktische Anwendung:
quelle
quelle
Wenn Sie überprüfen möchten, ob ein Verzeichnis vorhanden ist, unabhängig davon, ob es sich um ein echtes Verzeichnis oder einen Symlink handelt, verwenden Sie Folgendes:
Erläuterung: Der Befehl "ls" gibt den Fehler "ls: / x: Keine solche Datei oder kein solches Verzeichnis" aus, wenn das Verzeichnis oder der Symlink nicht vorhanden ist, und setzt auch den Rückkehrcode, den Sie über "$?" Abrufen können, auf non -null (normalerweise "1"). Stellen Sie sicher, dass Sie den Rückkehrcode direkt nach dem Aufruf von "ls" überprüfen.
quelle
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(1)
(2)
(3)
Wenn bei einem der oben genannten Ansätze ein Problem festgestellt wird:
Mit dem
ls
Befehl; In den Fällen, in denen kein Verzeichnis vorhanden ist, wird eine Fehlermeldung angezeigtquelle
Es gibt großartige Lösungen, aber letztendlich schlägt jedes Skript fehl, wenn Sie sich nicht im richtigen Verzeichnis befinden. Also Code wie folgt:
wird nur dann erfolgreich ausgeführt, wenn Sie sich zum Zeitpunkt der Ausführung in einem Verzeichnis befinden, in dem sich ein Unterverzeichnis befindet, nach dem Sie suchen.
Ich verstehe die anfängliche Frage wie folgt: um zu überprüfen, ob ein Verzeichnis existiert, unabhängig von der Position des Benutzers im Dateisystem. Die Verwendung des Befehls 'find' könnte also den Trick machen:
Diese Lösung ist gut, da sie die Verwendung von Platzhaltern ermöglicht, eine nützliche Funktion bei der Suche nach Dateien / Verzeichnissen. Das einzige Problem ist, dass, wenn das gesuchte Verzeichnis nicht existiert, der Befehl 'find' nichts in die Standardausgabe druckt (keine elegante Lösung für meinen Geschmack) und dennoch einen Null-Exit hat. Vielleicht könnte jemand dies verbessern.
quelle
locate
aber für nichts anderes ...