Ich habe einige Skripte geschrieben und so etwas geschrieben
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Was passiert ist, ist, dass ich aus Dummheit die zweite Zeile ausgeführt habe, ohne die erste auszuführen. Es stellte sich heraus, dass [-d ""] true zurückgibt und der Ausdruck wurde
rm -rf /*
Zum Glück war es nur eine Testmaschine und ich war kein Sudo, aber obwohl ich einige Daten verloren habe
Meine Frage ist, warum [-d ""] true zurückgibt? In der Dokumentation wird eindeutig angegeben, ob ein Pfad vorhanden ist und ein Ordner ist
Ich habe das Problem mit gelöst
[ -e $ARTIFACTS ]
das scheint zu funktionieren
Prost
rm -rf $ARTIFACTS
ohne das/*
. Dies würde auch das$ARTIFACTS
Verzeichnis löschen , was in Ordnung ist, denn wenn ich sicher sein möchte, dass es existiert, bevor ich etwas hineinlege, werde ich esmkdir -p $ARTIFACTS
trotzdem ausführen . Es werden auch versteckte Dateien darin gelöscht$ARTIFACTS
, was auch in Ordnung ist, da ich nicht schreiben würde,rm -rf $ARTIFACTS/*
wenn etwas$ARTIFACTS
enthalten wäre, das ich speichern wollte.Antworten:
1. Diese beiden Tests geben true zurück :
gemäß POSIX (wie von @Tim erklärt).
2. Dies gibt jedoch false zurück ( nicht true, wie in der Frage angegeben).
weil
test
wird mit zwei Argumenten aufgerufen (obwohl das zweite eine leere Zeichenfolge ist).3. Deshalb ist es eine gute Praxis,
[[ … ]]
anstelle vontest
([ … ]
) zu verwenden, was die meisten (alle?) Aktuellen Shells bieten. Dieses Konstrukt prüft, ob Sie genügend Argumente angeben (andernfalls wird ein Fehler ausgegeben und abgebrochen).oder verhält sich einfach so, wie man es erwarten würde:
4. Und wie von @Gilles hervorgehoben, ist es noch wichtiger, Substitutionen in doppelten Anführungszeichen zu setzen. So
-d "$SOME_UNSET_VAR"
dehnt sich auf-d ""
und kehrt falsch sogar mittest
(entspricht Fall 2). Daher ist dies auch mit der Bourne-Shell kompatibelsh
:getestet mit Bash 3.00.16 (1) und 4.1.5 (1)
quelle
[[ … ]]
aber nicht einfachsh
. Die wirklich wichtige Vorgehensweise besteht darin , Befehlsersetzungen in doppelte Anführungszeichen zu setzen :[ -d "$ARTIFACTS" ]
.Diese Frage wurde bereits auf StackOverflow beantwortet . Es heißt, dass gemäß dem POSIX-Standard
test
immer erfolgreich zurückgegeben werden sollte, wenn es mit genau einem nicht leeren Argument (und keinen anderen Argumenten) aufgerufen wird.Dies sollte auch bei
test -e
(und tatsächlich auf meinem System) der Fall sein , seien Sie also vorsichtig.Verwenden Sie stattdessen:
test
wird dann mit zwei Argumenten aufgerufen, auch wenn die Variable leer ist und in diesem Fall false zurückgibt.quelle
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
ist nicht besser: Es ist nur für den speziellen Fall geeignet, wenn$ARTIFACTS
es leer ist, schlägt jedoch fehl, wenn$ARTIFACTS
Leerzeichen oder enthalten können\[?*
.[ -d "$ARTIFACTS" ]
ist der richtige Weg, dies zu tun (oder[[ -d $ARTIFACTS ]]
in Muscheln, die haben[[ … ]]
).Du liegst falsch . Es funktioniert, weil
$ARTIFACTS
jetzt auf etwas eingestellt ist.Wenn eine Variable nicht gesetzt ist, dann sagen
oder
würde beide bewerten,
true
weil es sagtund
beziehungsweise. (Sprichwort
[ foobar ]
würde immer als wahr bewertet.)Sprichwort
ist in solchen Situationen nützlich.
help set
würde dir sagen:quelle
Stellen Sie sicher, dass Sie die Variable ARTIFACTS gesetzt und nach ARTIFCATS gesucht haben. Wahrscheinlich falsch tippen?
Auf jeden Fall würden -d und -e bei nicht gesetzten Variablen die gleichen Ergebnisse liefern.
Verwenden Sie daher doppelte Anführungszeichen und es wird Ihnen helfen.
HINWEIS: Wenn Ihr "/ SOME / PATH" einen Ordner mit Speicherplatz hat, wird das von Ihnen erwähnte Skript mit dem Fehler "Binäroperator erwartet" unterbrochen.
Beispiel:
wird gut tun. Vergessen Sie nicht, auch Anführungszeichen in den
rm
Aufruf aufzunehmen (rm -rf $ARTIFACTS
würde fröhlich entfernen und sich/home
dann überbackup/*
nicht existierende beschweren ).Durch die
-L
Überprüfung wird auch sichergestellt, dass es sich um ein Verzeichnis handelt und nicht nur um einen symbolischen Link zu einem Verzeichnis.Also im Grunde genommen,
quelle