it-swarm-es.com

¿Puedo determinar el número de subdirectorios en un directorio usando `LS -L`?

Al mostrar directorios usando ls -l, su número de enlaces (el segundo campo en la salida) es al menos dos: uno para el nombre de DIR y uno para .

$ mkdir foo
$ ls -l
total 2
drwxr-xr-x  2 user   wheel  512  4 oct 14:02 foo

¿Es seguro suponer siempre que la cantidad de enlaces anteriores se corresponde con el número de subdirectorios en este Dir (.. Enlaces) ?

8
Eugene Yarmash

Es generalmente VERDADERO en los sistemas UNIX que el número de enlaces a un directorio es el número de subdirectorios más 2. Sin embargo, hay casos en los que esto no es cierto :

  • Algunas imágenes permiten enlaces duros con los directorios. Luego habrá más de 2 enlaces que no corresponden a subdirectorios.

  • Hay sistemas de archivos donde los directorios no tienen entradas para . y ... El GNU Find Manual menciona algunos ejemplos en la discusión de su opción -noleaf (que deshabilita una optimización que supone que . y .. existen en todos los directorios): "CD-ROM o MS-DOS Files Systems o AFS Volume Mount Points"

Una forma casi confiable de contar el número de subdirectorios (aún puede fallar si un nombre de archivo contiene un carácter de nueva línea) es

$(($(LC_ALL=C ls -la /path/to/directory | grep '^d' | wc -l) - 2)

Una forma más confiable utiliza Shell Globs */ y .*/; Como es habitual, al manejar el caso donde el patrón no coincide es un poco de dolor (excepto en Bash y ZSH donde puede encender la opción nullglob).

Aquí está otra forma de contar subdirectorios (no recursivamente) en Bash:

(
shopt -s nullglob dotglob
printf '%s\000' */ | tr -dc '\0' | wc -c  # wc counts null bytes
)

Debido a que cada nombre de archivo se está terminando por un ASCII NUL, esto debería funcionar correctamente, incluso si un nombre de archivo contiene un carácter de nueva línea.

2
matt

No puedo encontrar nada en el Documentación que confirma que la cantidad de enlaces siempre será +2 en el número de subdirectorios.

Pero, para encontrar la cantidad correcta, use:

find . -type d -mindepth 1  -maxdepth 1 | wc -l

O si tienes que usar ls -l, vea la otra respuesta.

1
Stefan