Pregunta Compruebe si existe un directorio en un script de shell


¿Qué comando se puede usar para verificar si un directorio existe o no, dentro de un script de shell?


2988
2017-09-12 20:06


origen


Respuestas:


Para verificar si existe un directorio en un script de shell puede usar lo siguiente:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

O para verificar si un directorio no existe:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

Sin embargo, como Jon Ericson señala que los comandos posteriores pueden no funcionar como se espera si no se tiene en cuenta que un enlace simbólico a un directorio también pasará esta comprobación. P.ej. ejecutando esto:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Producirá el mensaje de error:

rmdir: failed to remove `symlink': Not a directory

Entonces, los enlaces simbólicos deben tratarse de manera diferente, si los siguientes comandos esperan directorios:

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

Tome nota de las comillas dobles utilizadas para ajustar las variables, el motivo de esto se explica por 8jean en otra respuesta.

Si las variables contienen espacios u otros caracteres inusuales, es probable que el script falle.


4132
2017-09-12 20:07



Recuerde siempre ajustar las variables entre comillas dobles al hacer referencia a ellas en un script bash Los niños en estos días crecen con la idea de que pueden tener espacios y muchos otros personajes divertidos en sus nombres de directorio. (¡Espacios! ¡De vuelta en mis días, no teníamos espacios elegantes!;))

Un día, uno de esos niños ejecutará tu script con $DIRECTORY ajustado a "My M0viez" y tu script explotará No quieres eso. Entonces usa esto

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

454
2017-09-15 22:00



Nota la -re la prueba puede producir algunos resultados sorprendentes:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

Archivo bajo: "¿Cuándo un directorio no es un directorio?" La respuesta: "Cuando se trata de un enlace simbólico a un directorio". Una prueba un poco más completa:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

Puede encontrar más información en el manual de Bash en Expresiones condicionales de Bash y el [ comando incorporado y el [[ Commmand compuesto.


203
2017-09-12 20:26



Encuentro el doble corchete versión de test hace que escribir pruebas de lógica sea más natural:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

198
2017-09-12 21:33



Forma más corta:

[ -d "$DIR" ] && echo "Yes"

125
2017-09-12 21:08



Para verificar si existe un directorio puede usar una estructura simple como esta:

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

Puedes hacerlo también en negativo

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

Nota: Tenga cuidado, deje espacios vacíos a cada lado de las llaves de apertura y cierre.

Con la misma sintaxis puedes usar:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 

118
2018-04-08 02:50



if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi

94
2018-04-15 08:07



Puedes usar test -d (ver man test)

-d file       Verdadero si el archivo existe y es un directorio.

Por ejemplo:

test -d "/etc" && echo Exists || echo Does not exist

Nota la test comando es lo mismo que expresión condicional [ (ver: man [), por lo que es portátil entre scripts de shell.

[ - Este es un sinónimo de test incorporado, pero el último argumento debe ser literal ], para que coincida con la apertura [.

Para posibles opciones o ayuda adicional, verifique:

  • help [
  • help test
  • man test o man [

73
2017-09-12 21:25



O por algo completamente inútil:

[ -d . ] || echo "No"

55
2017-08-17 14:02



Aquí hay un modismo muy pragmático:

(cd $dir) || return # is this a directory,
                    # and do we have access?

Normalmente lo envuelvo en una función:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

O:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

Lo bueno de este enfoque es que no tengo que pensar en un buen mensaje de error.

cd me dará un mensaje de una línea estándar para stderr ya. También proporcionará más información de la que podré proporcionar. Al realizar el cd dentro de una subshell ( ... ), el comando no afecta el directorio actual de la persona que llama. Si el directorio existe, esta subshell y la función son simplemente no-op.

El siguiente es el argumento que pasamos a cd: ${1:?pathname expected}. Esta es una forma más elaborada de sustitución de parámetros que se explica con más detalle a continuación.

Tl; dr: si la cadena que pasa a esta función está vacía, de nuevo salimos de la subcadena ( ... ) y regresa de la función con el mensaje de error dado.


Citando de la ksh93 página de hombre:

${parameter:?word}

Si parameter  está configurado y no es nulo, luego sustituye su valor;   de lo contrario, imprimir word y salir del shell (si no es interactivo).   Si word se omite, se imprime un mensaje estándar.

y

Si el colon : se omite de las expresiones anteriores, entonces el   shell solo comprueba si el parámetro está configurado o no.

El fraseo aquí es peculiar a la documentación del caparazón, como word puede referirse a cualquier cadena razonable, incluido el espacio en blanco.

En este caso particular, sé que el mensaje de error estándar 1: parameter not set no es suficiente, así que amplío el tipo de valor que esperamos aquí - el pathname de un directorio.

Una nota filosófica: El shell no es un lenguaje orientado a objetos, por lo que el mensaje dice pathnameno directory. En este nivel, prefiero mantenerlo simple: los argumentos para una función son solo cadenas.


46
2017-08-09 21:43