¿Cómo recorrer los directorios en Linux?

Estoy escribiendo un script en bash en Linux y necesito revisar todos los nombres de los subdirectorios en un directorio determinado. ¿Cómo puedo recorrer estos directorios (y omitir archivos regulares)?

Por ejemplo:
el directorio dado es /tmp/
tiene los siguientes subdirectorios: /tmp/A, /tmp/B, /tmp/C

Quiero recuperar A, B, C.

 cd /tmp find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' 

Una breve explicación: find archivos (obviamente)

  • . es el directorio actual, después del cd es /tmp (en mi humilde opinión esto es más flexible que tener /tmp directamente en el comando find. Solo tiene un lugar, el cd , para cambiar, si desea que se realicen más acciones en esta carpeta )

  • -maxdepth 1 y -mindepth 1 asegúrese, que find realmente, solo busca en el directorio actual y no incluye ‘ . ‘ en el resultado

  • -type d solo busca directorios

  • -printf '%f\n imprime solo el nombre de la carpeta encontrada (más una nueva línea) para cada hit.

E voila!

Todas las respuestas hasta ahora usan find , así que aquí hay una con solo el shell. No necesita herramientas externas en su caso:

 for dir in /tmp/*/ do dir=${dir%*/} echo ${dir##*/} done 

Puede recorrer todos los directorios, incluidas las direcciones ocultas (comenzando con un punto) con:

 for file in */ .*/ ; do echo "$file is a directory"; done 

Nota: el uso de la lista */ .*/ funciona en zsh solo si existe al menos un directorio oculto en la carpeta. En bash, se mostrará también . y ..


Otra posibilidad para bash para incluir directorios ocultos sería usar:

 shopt -s dotglob; for file in */ ; do echo "$file is a directory"; done 

Si desea excluir enlaces simbólicos:

 for file in */ ; do if [[ -d "$file" && ! -L "$file" ]]; then echo "$file is a directory"; fi; done 

Para generar solo el nombre del directorio final (A, B, C como cuestionado) en cada solución, use esto dentro de los bucles:

 file="${file%/}" # strip trailing slash file="${file##*/}" # strip path and leading slash echo "$file is the directoryname without slashes" 

Ejemplo (esto también funciona con directorios que contienen espacios):

 mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces" for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done 

Funciona con directorios que contienen espacios

Inspirado por Sorpigal

 while IFS= read -d $'\0' -r file ; do echo $file; ls $file ; done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0) 

Publicación original (no funciona con espacios)

Inspirado por Boldewyn : Ejemplo de bucle con comando de find .

 for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do echo $D ; done 
 find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n" 

La técnica que uso más a menudo es find | xargs find | xargs . Por ejemplo, si desea que todos los archivos de este directorio y todos sus subdirectorios sean legibles a nivel mundial, puede hacer:

 find . -type f -print0 | xargs -0 chmod go+r find . -type d -print0 | xargs -0 chmod go+rx 

La opción -print0 finaliza con un carácter NULO en lugar de un espacio. La opción -0 divide su entrada de la misma manera. Entonces esta es la combinación para usar en archivos con espacios.

Puede imaginarse que esta cadena de comandos toma cada salida de línea find y pegando al final de un comando chmod .

Si el comando que desea ejecutar es su argumento en el medio en lugar de al final, debe ser un poco creativo. Por ejemplo, necesitaba cambiar a cada subdirectorio y ejecutar el comando latemk -c . Entonces usé (de Wikipedia ):

 find . -type d -depth 1 -print0 | \ xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord 

Esto tiene el efecto de for dir $(subdirs); do stuff; done for dir $(subdirs); do stuff; done for dir $(subdirs); do stuff; done , pero es seguro para directorios con espacios en sus nombres. Además, las llamadas separadas a stuff se hacen en el mismo shell, por lo que en mi comando tenemos que volver al directorio actual con popd .

find . -type d -maxdepth 1

un bucle de bash mínimo desde el que puedes construir (basado en la respuesta de ghostdog74)

 for dir in directory/* do echo ${dir} done 

para comprimir un montón de archivos por directorio

 for dir in directory/* do zip -r ${dir##*/} ${dir} done