Comprobar si existe un directorio en un script de shell
Pregunta
¿Qué comando se puede utilizar para comprobar si un directorio existe o no, dentro de un script de shell?
Solución
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 comprobar 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, es posible que los comandos posteriores no funcionen según lo previsto si no se tiene en cuenta que un enlace simbólico a un directorio también pasará esta verificació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
Por lo tanto, es posible que los enlaces simbólicos deban tratarse de manera diferente, si los comandos posteriores 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 particular de las comillas dobles utilizadas para envolver las variables, el motivo de esto lo explica 8jean en otra respuesta.
Si las variables contienen espacios u otros caracteres inusuales, probablemente provocará que el script falle.
Otros consejos
Recuerde siempre envolver variables en citas dobles al hacerlas referirlas en un script bash.Los niños de hoy en día crecen con la idea de que pueden tener espacios y muchos otros personajes divertidos en los nombres de sus directorios.(¡Espacios!¡En mis días, no teníamos espacios lujosos!;))
Un día, uno de esos niños ejecutará tu script con $DIRECTORY
ajustado a "My M0viez"
y tu guión explotará.No quieres eso.Entonces usa esto.
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Nota la -d 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 es 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 [[
comando compuesto.
encuentro el doble soporte 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
Forma más corta:
[ -d "$DIR" ] && echo "Yes"
Para comprobar si existe un directorio, puede utilizar una estructura if 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 ambos lados de los tirantes 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
if [ -d "$DIRECTORY" ]; then
# Here if $DIRECTORY exists
fi
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:El test
El comando es lo mismo que la expresión condicional. [
(ver: man [
), por lo que es portátil entre scripts de shell.
[
- Este es un sinónimo detest
incorporado, pero el último argumento debe ser literal]
, para que coincida con la apertura[
.
Para posibles opciones o más ayuda, consulte:
help [
help test
man test
oman [
Un script simple para probar si el directorio o el archivo está presente o no:
if [ -d /home/ram/dir ] # for file "if [-f /home/rama/file]" then echo "dir present" else echo "dir not present" fi
Un script simple para verificar si el directorio está presente o no:
mkdir tempdir # if you want to check file use touch instead of mkdir ret=$? if [ "$ret" == "0" ] then echo "dir present" else echo "dir not present" fi
Los scripts anteriores comprobarán que el directorio esté presente o no.
$?
si el último comando es exitoso, devuelve "0"; de lo contrario, un valor distinto de cero.suponertempdir
ya esta presente entoncesmkdir tempdir
dará un error como el siguiente:mkdir:No se puede crear el directorio 'tempdir':El archivo existe
O por algo completamente inútil:
[ -d . ] || echo "No"
He aquí 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
Ya me dará un mensaje estándar de una línea a stderr.También proporcionará más información de la que yo podré proporcionar.Al realizar la cd
dentro de una subcapa ( ... )
, el comando no afecta el directorio actual de la persona que llama.Si el directorio existe, esta subcapa y la función simplemente no funcionan.
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.
Dr.:Si la cadena pasada a esta función está vacía, salimos nuevamente del subshell ( ... )
y regresar de la función con el mensaje de error dado.
Citando del ksh93
página de manual:
${parameter:?word}
Si
parameter
está establecido y no es nulo, entonces sustituya su valor;de lo contrario, imprimaword
y salir del shell (si no es interactivo).Siword
se omite, se imprime un mensaje estándar.
y
Si los dos puntos
:
se omite de las expresiones anteriores, entonces el shell solo verifica si el parámetro está configurado o no.
La redacción aquí es peculiar de la documentación del shell, ya que 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 me acerco al 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 pathname
, no directory
.En este nivel, prefiero mantenerlo simple: los argumentos de una función son solo cadenas.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
El código anterior comprueba si el directorio existe y si se puede escribir.
Escriba este código en el mensaje de bash
if [ -d "$DIRECTORY" ]; then
# if true this block of code will execute
fi
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 según 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, comprueba 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
En realidad, deberías utilizar varias herramientas para conseguir un enfoque a prueba de balas:
DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
echo "It's a dir";
fi
No hay necesidad de preocuparse por espacios y caracteres especiales siempre que utilice "${}"
.
Tenga en cuenta que [[]]
no es tan portátil como []
, pero dado que la mayoría de la gente trabaja con versiones modernas de Bash (ya que después de todo, la mayoría de la gente ni siquiera trabaja con la línea de comando :-p), el beneficio es mayor que el problema.
Para verificar más de un directorio use este código:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
¿Has considerado simplemente hacer lo que quieras hacer en el if
en lugar de mirar antes de saltar?
Es decir, si desea verificar la existencia de un directorio antes de ingresarlo, intente hacer esto:
if pushd /path/you/want/to/enter; then
# commands you want to run in this directory
popd
fi
Si el camino que le das pushd
existe, lo ingresarás y saldrá con 0
, lo que significa el then
parte de la declaración se ejecutará.Si no existe, no sucederá nada (aparte de algún resultado que indique que el directorio no existe, lo que probablemente sea un efecto secundario útil de todos modos para la depuración).
Parece mejor que esto, que requiere repetirlo:
if [ -d /path/you/want/to/enter ]; then
pushd /path/you/want/to/enter
# commands you want to run in this directory
popd
fi
Lo mismo funciona con cd
, mv
, rm
, etc...si los prueba en archivos que no existen, saldrán con un error e imprimirán un mensaje diciendo que no existe, y su then
Se omitirá el bloque.Si los prueba en archivos que existen, el comando se ejecutará y saldrá con un estado de 0
, permitiendo a su then
bloque a ejecutar.
Compruebe si el directorio existe; de lo contrario, cree uno.
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
NÓTESE BIEN:Citar variables es una buena práctica.
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
esta respuesta envuelto 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
es_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";
Utilizando el -e
check buscará archivos y esto incluye directorios.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
según jonathan comentario:
Si desea crear el directorio y aún no existe, entonces la técnica más sencilla es utilizar mkdir -p
que crea el directorio (y cualquier directorio que falte en la ruta) y no falla si el directorio ya existe, por lo que puedes hacerlo todo a la vez con:
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
Eso no es completamente cierto...Si desea ir a ese directorio, también necesita tener derechos de ejecución en el directorio.Quizás también necesites tener derechos de escritura.
Por lo tanto:
if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
# ... to go to that directory (even if DIRECTORY is a link)
cd $DIRECTORY
pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
# ... to go to that directory and write something there (even if DIRECTORY is a link)
cd $DIRECTORY
touch foobar
fi
El ls
comando en conjunto con -l
La opción (lista larga) devuelve información de atributos sobre archivos y directorios.
En particular, el primer personaje de ls -l
salida suele ser una d
o un -
(estrellarse).En caso de un d
el que aparece en la lista es un directorio con seguridad.
El siguiente comando en solo una línea le dirá si el dado ISDIR
La variable 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
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
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 existe 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 mediante "$?", en no nulo (normalmente "1").Asegúrese de verificar el código de retorno directamente después de llamar a "ls".
(1)
[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"
(2)
[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"
(3)
[[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists"
Si encuentra un problema con uno de los enfoques proporcionados anteriormente.
Con ls
dominio;Los casos en los que el directorio no existe: se muestra un mensaje de error.
$ [[ ls -ld SAMPLE_DIR| grep ^d | wc -l
-eq 1]] && echo existe || no existe -ksh:no:no encontrado [No existe tal archivo o directorio]
Existen excelentes soluciones, pero en última instancia, todos los scripts fallarán si no estás en el directorio correcto.Entonces codifique como este:
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á exitosamente sólo si en el momento de la ejecución estás en un directorio que tiene un subdirectorio que buscas.
Entiendo la pregunta inicial así:para verificar si un directorio existe independientemente de la posición del usuario en el sistema de archivos.Entonces, usar el comando 'buscar' podría ser la solución:
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 al buscar archivos/directorios.El único problema es que, si el directorio buscado no existe, el comando 'buscar' no imprimirá nada en la salida estándar (no es una solución elegante para mi gusto) y, no obstante, tendrá una salida cero.Quizás alguien podría mejorar esto.
A continuación se puede utilizar la búsqueda,
find . -type d -name dirname -prune -print