Estaba escribiendo algunos guiones y escribí algo como
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Lo que sucedió es que por estupidez ejecuté la segunda línea sin ejecutar la primera. Resultó que [-d ""] devuelve verdadero y la expresión se convirtió en
rm -rf /*
Afortunadamente era solo una máquina de prueba y no era un sudo, pero aunque perdí algunos datos
Mi pregunta es, ¿por qué [-d ""] devuelve verdadero? la documentación indica claramente que verifica si existe una ruta y si es una carpeta
Resolví el problema usando
[ -e $ARTIFACTS ]
que parece funcionar
Salud
rm -rf $ARTIFACTS
sin el/*
. Esto también eliminaría el$ARTIFACTS
directorio, lo cual está bien, porque si quiero estar seguro de que existe antes de poner algo en él, lo ejecutaré demkdir -p $ARTIFACTS
todos modos. También eliminará los archivos ocultos dentro$ARTIFACTS
, lo cual también está bien, porque no escribiríarm -rf $ARTIFACTS/*
si$ARTIFACTS
contuviera algo que quisiera guardar.Respuestas:
1. Estas dos pruebas devuelven verdadero :
de acuerdo con POSIX (como lo explica @Tim).
2. Pero esto devuelve falso ( no es cierto como se indica en la pregunta)
porque
test
se llama con dos argumentos (aunque el segundo es una cadena vacía).3. Es por eso que es una buena práctica usar en
[[ … ]]
lugar detest
([ … ]
), que proporcionan la mayoría (¿todos?) De los shells actuales. Esta construcción verifica si proporciona suficientes argumentos (de lo contrario, arroja un error y aborta)o simplemente se comporta como uno esperaría:
4. Y, como señaló @Gilles, aún más importante es duplicar las sustituciones. Por lo tanto, se
-d "$SOME_UNSET_VAR"
expande-d ""
y devuelve falso incluso contest
(igual al caso 2). Por lo tanto, esto también es compatible con el shell Bournesh
:probado con bash 3.00.16 (1) y 4.1.5 (1)
fuente
[[ … ]]
pero no son simplessh
. La práctica realmente importante es poner comillas dobles sustituciones de comando :[ -d "$ARTIFACTS" ]
.Esta pregunta ya ha sido respondida en StackOverflow. Dice que de acuerdo con el estándar POSIX,
test
siempre debe devolverse con éxito si se llama con exactamente un argumento no vacío (y sin otros argumentos).Este también debería ser el caso con
test -e
(y de hecho está en mi sistema), así que tenga cuidado.En su lugar use:
test
luego se llamará con dos argumentos incluso si la variable está vacía y devuelve falso en este caso.fuente
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
no es mejor: solo atiende el caso particular cuando$ARTIFACTS
está vacío, pero falla cuando$ARTIFACTS
puede contener espacios en blanco o\[?*
.[ -d "$ARTIFACTS" ]
es la forma correcta de hacerlo (o[[ -d $ARTIFACTS ]]
en shells que lo tienen[[ … ]]
).Estás equivocado . Funciona porque
$ARTIFACTS
ahora está configurado en algo.Cuando no se establece una variable, entonces decir
o
sería tanto evaluar a
true
porque implica diciendoy
respectivamente. (Decir
[ foobar ]
siempre se evaluaría como verdadero).Diciendo
resulta útil en tales situaciones.
help set
te diría:fuente
Vea que configuró la variable ARTIFACTS y que estaba buscando ARTIFCATS. ¿Probablemente escribiendo mal?
De todos modos, -d así como -e producirían los mismos resultados en variables no establecidas.
Por lo tanto, use comillas dobles y le ayudará.
NOTA: Si su "/ SOME / PATH" tiene alguna carpeta con espacio, el script que mencionó se romperá con el error "operador binario esperado".
Ejemplo:
Lo haré bien. No olvide poner también comillas en la
rm
invocación (rm -rf $ARTIFACTS
eliminaría alegremente y/home
luego se quejaría porbackup/*
no existir).Además, incluir la
-L
verificación se asegurará de que sea un directorio y no solo un enlace simbólico a un directorio.Así que básicamente,
fuente