Para encontrar solo los directorios hoja que contienen archivos, puede combinar una respuesta de la pregunta a la que se hace referencia https://unix.stackexchange.com/a/203991/330217 o preguntas similares https://stackoverflow.com/a/4269862/10622916 o https://serverfault.com/a/530328 con find
! -empty
de
find rootdir -type d -links 2 ! -empty
Comprobando los enlaces duros con -links 2
debería funcionar para los sistemas de archivos UNIX tradicionales. El -empty
condición no es parte del estándar POSIX, pero debería estar disponible en la mayoría de los sistemas Linux.
Según el comentario de KamilMaciorowski, la semántica de recuento de enlaces tradicional para directorios no es válida para Btrfs. Esto se confirma en https://linux-btrfs.vger.kernel.narkive.com/oAoDX89D/btrfs-st-nlink-for-directories, que también menciona a Mac OS HFS+ como una excepción al comportamiento tradicional. Para estos sistemas de archivos, se necesita un método diferente para verificar los directorios hoja.
Podrías usar find
anidado y cuenta el número de subdirectorios:
find . -type d \
\( -exec sh -c 'find "$1" -mindepth 1 -maxdepth 1 -type d -print0 | grep -cz "^" >/dev/null 2>&1' _ {} \; -o -print \)
Si el */
el patrón de globbing de nombre de archivo se expande a algo que no es el nombre de un directorio, entonces el directorio actual no tiene subdirectorios (no ocultos).
Con find
:
find root -type d -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; ! -empty -print
Tenga en cuenta que esto trataría un enlace simbólico a un directorio en un directorio hoja como un directorio ya que el patrón atravesaría el enlace simbólico.
El -empty
El predicado no es estándar, pero a menudo se implementa. Sin él, haría algo similar a la detección de subdirectorios:
find root -type d \
-exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print
O, un poco más eficiente,
find root -type d -exec sh -c '
dir=$1
set -- "$dir"/*/
[ -d "$1" ] && exit 1
set -- "$dir"/*
[ -e "$1" ]' sh {} \; -print
O, empleando el -links
predicado que me había olvidado (gracias Bodo):
find root -type d \
-links 2 \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print