J'écrivais des scripts et écrivais quelque chose comme
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Ce qui s'est passé, c'est que par stupidité j'ai exécuté la deuxième ligne sans exécuter la première. Il s'est avéré que [-d ""] renvoie vrai et l'expression est devenue
rm -rf /*
Heureusement, ce n'était qu'une machine de test et je n'étais pas un sudo, mais même si j'ai perdu des données
Ma question est, pourquoi [-d ""] retourne vrai ?? la documentation indique clairement qu'il vérifie si un chemin existe et s'il s'agit d'un dossier
J'ai résolu le problème en utilisant
[ -e $ARTIFACTS ]
qui semble fonctionner
À votre santé
rm -rf $ARTIFACTS
sans/*
. Cela supprimerait également le$ARTIFACTS
répertoire, ce qui est bien, car si je veux être sûr qu'il existe avant d'y mettre quelque chose, je l'exécuteraimkdir -p $ARTIFACTS
quand même. Il supprimera également les fichiers cachés à l'intérieur$ARTIFACTS
, ce qui est également bien, car je n'écrirais pasrm -rf $ARTIFACTS/*
s'il$ARTIFACTS
contenait quelque chose que je voulais enregistrer.Réponses:
1. Ces deux tests retournent vrai :
selon POSIX (comme expliqué par @Tim).
2. Mais cela retourne faux ( pas vrai comme indiqué dans la question)
car
test
est appelé avec deux arguments (bien que le second soit une chaîne vide).3. C'est pourquoi il est recommandé d'utiliser à la
[[ … ]]
place detest
([ … ]
), que la plupart (tous?) Des shells actuels fournissent. Cette construction vérifie si vous fournissez suffisamment d'arguments (sinon lance une erreur et abandonne)ou se comporte simplement comme on pourrait s'y attendre:
4. Et, comme l'a souligné @Gilles, il est encore plus important de doubler les substitutions de guillemets. Ainsi , se
-d "$SOME_UNSET_VAR"
développe pour-d ""
et retourne faux mêmetest
(égal au cas 2). C'est donc également compatible avec le shell Bournesh
:testé avec bash 3.00.16 (1) et 4.1.5 (1)
la source
[[ … ]]
mais pas simplesh
. La pratique vraiment important est de mettre des guillemets doubles autour de substitutions de commandes :[ -d "$ARTIFACTS" ]
.Cette question a déjà été répondue sur StackOverflow. Il indique que selon la norme POSIX,
test
devrait toujours retourner avec succès s'il est appelé avec exactement un argument non vide (et aucun autre argument).Cela devrait également être le cas avec
test -e
(et en fait c'est sur mon système), alors soyez prudent.Utilisez plutôt:
test
sera alors appelé avec deux arguments même si la variable est vide et retourne false dans ce cas.la source
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
n'est pas mieux: il ne s'adresse qu'au cas particulier lorsqu'il$ARTIFACTS
est vide, mais échoue lorsqu'il$ARTIFACTS
peut contenir des espaces ou\[?*
.[ -d "$ARTIFACTS" ]
est la bonne façon de le faire (ou[[ -d $ARTIFACTS ]]
dans des coquilles qui ont[[ … ]]
).Vous vous trompez . Cela fonctionne parce que
$ARTIFACTS
est maintenant réglé sur quelque chose.Lorsqu'une variable n'est pas définie, dire
ou
serait à la fois évaluer
true
car cela implique de direet
respectivement. (En disant
[ foobar ]
serait toujours vrai.)En disant
est utile dans de telles situations.
help set
vous dirait:la source
Vérifiez que vous définissez la variable ARTIFACTS et que vous recherchez ARTIFCATS. Probablement une faute de frappe?
Quoi qu'il en soit, -d ainsi que -e produiraient les mêmes résultats sur les variables non définies.
Par conséquent, utilisez des guillemets doubles et cela vous aidera.
REMARQUE: si votre "/ SOME / PATH" contient un dossier avec de l'espace, le script que vous avez mentionné rompra avec l'erreur "opérateur binaire attendu".
Exemple:
fera bien. N'oubliez pas de mettre également des guillemets dans l'
rm
invocation (rm -rf $ARTIFACTS
supprimer joyeusement/home
puis se plaindre debackup/*
ne pas exister).En outre, y compris
-L
check vous assurera qu'il s'agit d'un répertoire et pas seulement d'un lien symbolique vers un répertoire.Donc en gros,
la source