2011-10-31 03:47:31 +0000 2011-10-31 03:47:31 +0000
106
106

Scripting Bash: prueba de directorio vacío

Quiero comprobar si un directorio no contiene ningún archivo. Si es así, me saltaré algún proceso.

He probado lo siguiente:

if [./* == "./*"]; then
    echo "No new file"
    exit 1
fi

Eso da el siguiente error:

line 1: [: too many arguments

¿Hay alguna solución/alternativa?

Respuestas (18)

135
135
135
2011-10-31 03:53:28 +0000
if [-z "$(ls -A /path/to/dir)"]; then
   echo "Empty"
else
   echo "Not Empty"
fi

Además, estaría bien comprobar si el directorio existe antes.

24
24
24
2013-10-29 21:07:29 +0000

No es necesario contar nada ni los globos de la cáscara. También puede utilizar read en combinación con find. Si la salida de find está vacía, devolverá false:

if find /some/dir -mindepth 1 | read; then
   echo "dir not empty"
else
   echo "dir empty"
fi

Esto debería ser portable.

20
20
20
2011-10-31 10:53:57 +0000
if [-n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)"]; then
    echo "Empty directory"
else
    echo "Not empty or NOT a directory"
fi
14
14
14
2011-11-01 14:51:09 +0000
#!/bin/bash
if [-d /path/to/dir]; then
    # the directory exists
    ["$(ls -A /path/to/dir)"] && echo "Not Empty" || echo "Empty"
else
    # You could check here if /path/to/dir is a file with [-f /path/to/dir]
fi
4
4
4
2018-09-26 13:50:40 +0000

Con FIND(1) (en Linux y FreeBSD) puede buscar de forma no recursiva en una entrada de directorio mediante “-maxdepth 0” y comprobar si está vacía con “-empty”. Aplicado a la pregunta esto da:

if test -n "$(find ./ -maxdepth 0 -empty)" ; then
    echo "No new file"
    exit 1
fi
4
4
4
2014-10-24 01:23:28 +0000

Una manera hacky, pero sólo en bash, sin PID:

is_empty() {
    test -e "$1/"* 2>/dev/null
    case $? in
        1) return 0 ;;
        *) return 1 ;;
    esac
}

Esto aprovecha el hecho de que el builtin test sale con 2 si se le da más de un argumento después de -e: Primero, "$1"/* glob es expandido por bash. Esto resulta en un argumento por archivo. Así que

  • Si no hay archivos, el asterisco en test -e "$1"* no se expande, por lo que Shell vuelve a probar el archivo llamado *, que devuelve 1.

  • …excepto si realmente hay un archivo llamado exactamente *, entonces el asterisco se expande a bueno, asterisco, que termina como la misma llamada de arriba, es decir, test -e "dir/*", sólo que esta vez devuelve 0. (Gracias @TrueY por señalar esto. )

  • Si hay un archivo, se ejecuta test -e "dir/file", que devuelve 0.

  • Pero si hay más archivos que 1, se ejecuta test -e "dir/file1" "dir/file2", que bash reporta como error de uso, es decir, 2.

case envuelve toda la lógica para que sólo el primer caso, con estado de salida 1 sea reportado como éxito.

Posibles problemas que no he comprobado:

  • Hay más archivos que el número de argumentos permitidos–supongo que esto podría comportarse de forma similar al caso con 2+ archivos.

  • O hay realmente un archivo con un nombre vacío–no estoy seguro de que sea posible en cualquier SO/FS sano.

4
4
4
2011-10-31 10:06:28 +0000

Esto hará el trabajo en el directorio de trabajo actual (.):

[`ls -1A . | wc -l` -eq 0] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."

o el mismo comando dividido en tres líneas para que sea más legible:

[`ls -1A . | wc -l` -eq 0] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."

Simplemente sustituya ls -1A . | wc -l por ls -1A <target-directory> | wc -l si necesita ejecutarlo en una carpeta de destino diferente.

Edición : He sustituido -1a por -1A (ver comentario de @Daniel)

3
3
3
2011-10-31 10:17:15 +0000

Utiliza lo siguiente:

count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [$count -eq 0] ; then
   echo "No new file"
   exit 1
fi

De esta manera, es independiente del formato de salida de ls. -mindepth se salta el directorio en sí, -maxdepth evita defender recursivamente en subdirectorios para acelerar las cosas.

3
3
3
2014-08-12 21:46:08 +0000

Utilizando un array:

files=( * .* )
if (( ${#files[@]} == 2 )); then
    # contents of files array is (. ..)
    echo dir is empty
fi
2
2
2
2018-06-20 09:17:01 +0000

¿Qué hay de probar si el directorio existe y no está vacío en una sentencia if

if [[-d path/to/dir && -n "$(ls -A path/to/dir)"]]; then 
  echo "directory exists"
else
  echo "directory doesn't exist"
fi
1
1
1
2013-10-29 20:57:27 +0000

Creo que la mejor solución es:

files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[["$files"]] || echo "dir empty"

gracias a https://stackoverflow.com/a/91558/520567

Esto es una edición anónima de mi respuesta que puede o no ser útil para alguien: Una ligera alteración da el número de archivos:

files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]}) 
echo "MYPATH contains $files files"

Esto funcionará correctamente incluso si los nombres de los archivos contienen espacios.

1
1
1
2020-02-16 18:53:46 +0000

La pregunta era:

if [./* == "./*"]; then
    echo "No new file"
    exit 1
fi

La respuesta es:

if ls -1qA . | grep -q .
    then ! exit 1
    else : # Dir is empty
fi
1
1
1
2018-05-25 17:06:53 +0000
if find "${DIR}" -prune ! -empty -exit 1; then
    echo Empty
else
    echo Not Empty
fi

EDIT: Creo que esta solución funciona bien con gnu find, después de un rápido vistazo a la implementación . Pero puede que no funcione con, por ejemplo, el find de netbsd . En efecto, ese utiliza el campo st_tamaño de stat(2). El manual lo describe como

st_size The size of the file in bytes. The meaning of the size
                   reported for a directory is file system dependent.
                   Some file systems (e.g. FFS) return the total size used
                   for the directory metadata, possibly including free
                   slots; others (notably ZFS) return the number of
                   entries in the directory. Some may also return other
                   things or always report zero.

Una solución mejor, también más sencilla, es:

if find "${DIR}" -mindepth 1 -exit 1; then
    echo Empty
else
    echo Not Empty
fi

Además, el -prune de la 1ª solución es inútil.

EDIT: no hay -exit para gnu find.. la solución anterior es buena para el find de NetBSD. Para GNU find, esto debería funcionar:

if [-z "`find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit`"]; then
    echo Empty
else
    echo Not Empty
fi
0
0
0
2020-01-15 17:46:01 +0000

Hice este planteamiento:

CHECKEMPTYFOLDER=$(test -z "$(ls -A /path/to/dir)"; echo $?)
if [$CHECKEMPTYFOLDER -eq 0]
then
  echo "Empty"
elif [$CHECKEMPTYFOLDER -eq 1]
then
  echo "Not Empty"
else
  echo "Error"
fi
0
0
0
2018-05-02 13:29:51 +0000

Esto funciona para mí, para comprobar y procesar los archivos en el directorio ../IN, teniendo en cuenta que el script está en el directorio ../Script:

FileTotalCount=0

    for file in ../IN/*; do
    FileTotalCount=`expr $FileTotalCount + 1`
done

if test "$file" = "../IN/*"
then

    echo "EXITING: NO files available for processing in ../IN directory. "
    exit

else

  echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."

# Rest of the Code
0
0
0
2012-02-24 10:06:37 +0000

Todo esto es muy bueno - sólo lo hizo en un script para que pueda comprobar si hay directorios vacíos por debajo de la actual. El siguiente debe ser puesto en un archivo llamado ‘findempty’, colocado en la ruta en algún lugar para que bash pueda encontrarlo y luego chmod 755 para ejecutar. Puede ser fácilmente modificado a sus necesidades específicas, supongo.

#!/bin/bash
if ["$#" == "0"]; then 
find . -maxdepth 1 -type d -exec findempty "{}" \;
exit
fi

COUNT=`ls -1A "$*" | wc -l`
if ["$COUNT" == "0"]; then 
echo "$* : $COUNT"
fi
-1
-1
-1
2018-01-10 17:12:56 +0000

Para cualquier directorio que no sea el actual, puedes comprobar si está vacío intentando rmdir, porque rmdir está garantizado que falla para los directorios no vacíos. Si rmdir tiene éxito, y usted realmente quería que el directorio vacío sobreviviera a la prueba, sólo tiene que volver a mkdir.

No utilice este truco si hay otros procesos que podrían verse desconcertados por un directorio que conocen y que deja de existir brevemente.

Si rmdir no le funciona, y puede que esté probando directorios que podrían contener un gran número de archivos, cualquier solución que dependa del globbing del shell podría volverse lenta y/o toparse con los límites de longitud de la línea de comandos. Probablemente sea mejor usar find en ese caso. La solución más rápida de find que se me ocurre es como

is_empty() {
    test -z $(find "$1" -mindepth 1 -printf X -quit)
}

Esto funciona para las versiones GNU y BSD de find pero no para la de Solaris, a la que le faltan todos y cada uno de esos operadores find. Me encanta tu trabajo, Oracle.

-3
-3
-3
2018-04-08 20:54:13 +0000

Puede intentar eliminar el directorio y esperar a que se produzca un error; rmdir no eliminará el directorio si no está vacío.

_path="some/path"
if rmdir $_path >/dev/null 2>&1; then
   mkdir $_path # create it again
   echo "Empty"
else
   echo "Not empty or doesn't exist"
fi