¿Cómo cuento todos los archivos de forma recursiva a través de directorios?

48

Quiero ver cuántos archivos hay en subdirectorios para saber dónde está todo el uso de inodo en el sistema. Algo así como lo haría para el uso del espacio

du -sh /*

lo que me dará el espacio utilizado en los directorios fuera de la raíz, pero en este caso quiero la cantidad de archivos, no el tamaño.

xenoterracida
fuente
Creo que "cuántos archivos hay en subdirectorios en sus subdirectorios" es una construcción confusa. Si indica más claramente lo que desea, puede obtener una respuesta que se ajuste a la factura.
Steven D
@ Steven no dude en reescribirlo ... Pensé que mi ejemplo du -sh /*dejaba bastante claro cómo quería que funcionara el conteo. Lo mismo, solo cuenta los archivos, no los bytes.
xenoterracida
Como mencionas el uso de inodes, no entiendo si quieres contar la cantidad de archivos o la cantidad de inodos usados. Los dos son diferentes cuando hay enlaces duros en el sistema de archivos. La mayoría, si no todas, las respuestas dan el número de archivos. No los use en un disco de respaldo Apple Time Machine.
mouviciel
@mouviciel, esto no se está utilizando en un disco de respaldo, y sí, supongo que podrían ser diferentes, pero en el entorno en el que estoy hay muy pocos enlaces duros, técnicamente solo necesito tener una idea. averiguar dónde se está quemando alguien allí dentro de la cuota de inodo.
xenoterracide

Respuestas:

61
find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Gracias a Gilles y xenoterracide por las soluciones de seguridad / compatibilidad.

La primera parte: find -maxdepth 1 -type ddevolverá una lista de todos los directorios en el directorio de trabajo actual. Esto se canaliza a ...

La segunda parte: while read -r dir; docomienza un ciclo while, siempre que la tubería que entra en while esté abierta (que es hasta que se envíe la lista completa de directorios), el comando de lectura colocará la siguiente línea en la variable "dir". Entonces continúa ...

La tercera parte: printf "%s:\t" "$dir";se imprimirá en la cadena "$ dir" (que es la celebración de uno de los nombres de directorio), seguido de una ficha.

La cuarta parte: find "$dir -f file"hace una lista de todos los archivos dentro del nombre del directorio contenido en "$ dir". Esta lista se envía a ...

La quinta parte: wc -l;cuenta el número de líneas que se envían a su entrada estándar.

La parte final: donesimplemente finaliza el ciclo while.

Entonces obtenemos una lista de todos los directorios en el directorio actual. Para cada uno de esos directorios, generamos una lista de todos los archivos en él para que podamos contarlos todos usando wc -l. El resultado se verá así:

./dir1: 234
./dir2: 11
./dir3: 2199
...
Shawn J. Goff
fuente
Úselo siempre read -rcomo readgolosinas simples especialmente. Luego echo -en "$dir:\t"volverá a destrozar las barras invertidas; una solución simple es usar printf '%s:\t' "$dir"en su lugar. A continuación, $dirdebe ser "$dir"( siempre use comillas dobles alrededor de sustituciones variables ).
Gilles 'SO- deja de ser malvado'
modificado según las sugerencias de @Gilesfind -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
xenoterracide
2
Estoy agregando sort -n -r -k2al final de esto, para muchos directorios, para saber dónde es el mayor uso
xenoterracide
La cuarta parte: buscar "$ dir" hace una lista de todos los archivos dentro del nombre del directorio contenido en "$ dir". Se olvidó de agregar -type fpara que find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
aparezca
1
No estoy haciendo que esto funcione en macOS Sierra 10.12.5. illegal option -- men el findcomando Lo cambié find . -maxdepth ...y lo puse a trabajar.
Jeff
15

Intente find . -type f | wc -l, contará todos los archivos en el directorio actual, así como todos los archivos en subdirectorios. Tenga en cuenta que todos los directorios no se contarán como archivos, solo los archivos normales sí.

herohuyongtao
fuente
13

Aquí hay una compilación de algunos comandos útiles de listado (re-hash basado en el código de los usuarios anteriores):

Lista de carpetas con recuento de archivos:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

Lista de carpetas con un recuento de archivos distinto de cero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Lista de carpetas con recuento de subcarpetas:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

Lista de carpetas con recuento de subcarpetas distinto de cero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Lista de carpetas vacías:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Lista de carpetas no vacías con conteo de contenido:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done
DolphinDream
fuente
Y por cierto ... si desea tener la salida de cualquiera de estos comandos de lista ordenados por el recuento de elementos ... canalice el comando en una clasificación: "a-list-command" | sort -n
DolphinDream
12

Tratar:

find /path/to/start/at -type f -print | wc -l

como punto de partida, o si realmente solo desea recurrir a través de los subdirectorios de un directorio (y omitir los archivos en ese directorio de nivel superior)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l
Llora Havok
fuente
+1 por algo | wc -l ... el conteo de palabras es una pequeña herramienta tan agradable
Johan
sí, pero esto solo hace 1 directorio ... Me gustaría obtener el recuento de todos los directorios en un directorio, y no quiero ejecutarlo por separado cada vez ... por supuesto, supongo que podría usar un bucle ... pero estoy siendo flojo.
xenoterracide
findfunciona de forma recursiva a través de todos los subdirectorios por defecto. Si desea que funcione en varias ubicaciones, puede especificarlas todas entre findy -type.
Didier Trosset
ese segundo ciertamente no funciona ... Lo probé en / home. Llegué 698035 . Debería ver unos 6 números.
xenoterracide
Funciona para mí, ¿estás seguro de que solo tienes 6 archivos /home? Estaría 100% seguro de que no.
Cry Havok
4

La siguiente solución cuenta el número real de inodos usados ​​a partir del directorio actual:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Para obtener el número de archivos del mismo subconjunto, use:

find . | wc -l

Para soluciones que exploran solo subdirectorios, sin tener en cuenta los archivos en el directorio actual, puede consultar otras respuestas.

Mouviciel
fuente
1
Buena idea teniendo en cuenta los enlaces duros. Suponiendo hallazgo de GNU, que no necesita tantos pasos: find -printf '%i\n' | sort -u | wc -l. Si quisieras ser portátil, necesitarías en su find . -exec ls -id {} + | cut …lugar.
Gilles 'SO- deja de ser malvado'
2

OS X 10.6 se ahoga con el comando en la respuesta aceptada, porque no especifica una ruta para find. En su lugar use:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
abeboparebop
fuente
2

Sé que llego tarde a la fiesta, pero creo que esta bashsolución pura (u otra concha que acepta el doble globo de estrellas) podría ser mucho más rápida en algunas situaciones:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

salida:

d1/:    302
d2/:    24
d3/:    640
...
jimmij
fuente
1

Prueba esto:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%s\t%s\n" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

Debería funcionar bien a menos que los nombres de archivo incluyan nuevas líneas.

Dennis Williamson
fuente
demasiado recursivo ... Solo quiero ver el nivel superior, donde totaliza todo lo que hay debajo. totalizado ... esto termina imprimiendo cada directorio.
xenoterracide
@xenoterracide: intente agregar -maxdepth 1inmediatamente después del primero find. Si desea incluir el número de subdirectorios en su recuento, elimine -type fal final (eso debería haber sido de ! -type dtodos modos, para que todos los archivos que no sean de directorio se hubieran incluido).
Dennis Williamson el
1

Si tiene ncduinstalado (algo que debe tener cuando quiere hacer una limpieza), simplemente escriba c"Alternar visualización de recuentos de elementos secundarios". Y Cpara "Ordenar por elementos".

Semiluna
fuente
1
jajaja, esta debe ser la respuesta más aceptada :)
x-yuri
0

du --inodes

No estoy seguro de por qué nadie (incluido yo) sabía:

du --inodes
--inodes
      list inode usage information instead of block usage

Estoy bastante seguro de que esto resuelve el problema del OP. He comenzado a usarlo mucho para descubrir dónde está toda la basura en mis enormes unidades (y descargarla en un disco más antiguo).

Informacion adicional

Si NO desea recurrir (que puede ser útil en otras situaciones), agregue

-S, --separate-dirs
Sridhar Sarnobat
fuente