Compruebe si existe un directorio en un script de shell


Answers

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 configurado en "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
Question

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




Tenga en cuenta que la prueba -d 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 sobre las expresiones condicionales de Bash y el [ comando incorporado y el [[ commmand compuesto .




El comando ls junto con la opción -l (lista larga) devuelve información de atributos sobre archivos y directorios.
En particular, el primer carácter de la salida ls -l suele ser una d o una - (guión). En caso de una d la lista es un directorio seguro.

El siguiente comando en una sola línea le dirá si la variable ISDIR dada contiene una ruta a un directorio o no:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

Uso práctico:

    [claudio@nowhere ~]$ ISDIR="$HOME/Music" 
    [claudio@nowhere ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [claudio@nowhere ~]$ touch "empty file.txt"
    [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" 
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory



Esta respuesta concluyó como un script de shell

Ejemplos

$ is_dir ~                           
YES

$ is_dir /tmp                        
YES

$ is_dir ~/bin                       
YES

$ mkdir '/tmp/test me'

$ is_dir '/tmp/test me'
YES

$ is_dir /asdf/asdf                  
NO

# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
  echo "Folder doesnt exist: $DIR";
  exit;
fi

is_dir

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";



Más funciones usando find

  • Verifique la existencia de la carpeta dentro de los subdirectorios:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
    
  • Verifique la existencia de una o varias carpetas basadas en un patrón dentro del directorio actual:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
    
  • Ambas combinaciones En el siguiente ejemplo, verifica la existencia de la carpeta en el directorio actual:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi
    



Según comenta:

Si desea crear el directorio y aún no existe, entonces la técnica más simple es usar mkdir -p que crea el directorio, y los directorios que faltan en la ruta, y no falla si el directorio ya existe, para que pueda hazlo todo de una vez con:

mkdir -p /some/directory/you/want/to/exist || exit 1



Escriba este código en la etiqueta bash

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi



Verifique si el directorio existe, sino haga uno

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY



Si desea verificar si existe un directorio, independientemente de si es un directorio real o un enlace simbólico, use esto:

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

Explicación: El comando "ls" da un error "ls: / x: No hay tal archivo o directorio" si el directorio o enlace simbólico no existe, y también establece el código de retorno, que puede recuperar a través de "$?", A no -null (normalmente "1"). Asegúrese de verificar el código de retorno directamente después de llamar a "ls".




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 ejecutar el cd dentro de una subcadena ( ... ) , 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 regresamos de la función con el mensaje de error dado.

Citando de la página man de ksh93 :

${parameter:?word}

Si el parameter está establecido y no es nulo, sustituya su valor; de lo contrario, imprima la word y salga del intérprete (si no es interactivo). Si se omite la word se imprimirá un mensaje estándar.

y

Si los dos puntos : se omiten de las expresiones anteriores, el shell solo verifica si el parámetro está configurado o no.

El fraseo aquí es peculiar a la documentación del shell, ya que la 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 es suficiente, así que amplío el tipo de valor que esperamos aquí: la pathname de pathname de un directorio.

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




Existen excelentes soluciones, pero finalmente cada script fallará si no está en el directorio correcto. Así que codifique así:

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

se ejecutará correctamente solo si en el momento de la ejecución está en un directorio que tiene un subdirectorio que usted verifica.

Entiendo la pregunta inicial de esta manera: para verificar si existe un directorio independientemente de la posición del usuario en el sistema de archivos. Entonces, usar el comando 'buscar' podría hacer el truco:

dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d

Esta solución es buena porque permite el uso de comodines, una característica útil cuando se buscan archivos / directorios. El único problema es que, si el directorio buscado no existe, el comando 'buscar' no imprimirá nada en stdout (no es una solución elegante para mi gusto) y tendrá, sin embargo, una salida cero. Tal vez alguien podría mejorar en esto.




[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

NB: Citar variables es una buena práctica.




Git Bash + Dropbox + Windows:

Ninguna de las otras soluciones funcionó para mi carpeta de Dropbox, lo cual era extraño porque puedo presionar la ruta simbólica Dropbox.

#!/bin/bash

dbox="~/Dropbox/"
result=0
prv=$(pwd) && eval "cd $dbox" && result=1 && cd "$prv"
echo $result

read -p "Press Enter To Continue:"

Probablemente también quieras saber cómo navegar exitosamente a dropbox desde bash. Así que aquí está el guión en su entiridad.

https://pastebin.com/QF2Exmpn




Puedes usar test -d (ver man test ).

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

Por ejemplo:

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

Nota: El comando de test es igual que la expresión condicional [ (see: man [ ), por lo que es portátil entre los scripts del shell.

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

Para posibles opciones o ayuda adicional, verifique:

  • help [
  • help test
  • man test u man [



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 



Related