Esto parece funcionar bastante bien:
find . -type f -print0 | xargs -0 ls -l | awk '{size[int(log($5)/log(2))]++}END{for (i in size) printf("%10d %3d\n", 2^i, size[i])}' | sort -n
Su salida se ve así:
0 1
8 3
16 2
32 2
64 6
128 9
256 9
512 6
1024 8
2048 7
4096 38
8192 16
16384 12
32768 7
65536 3
131072 3
262144 3
524288 6
2097152 2
4194304 1
33554432 1
134217728 4
donde el número de la izquierda es el límite inferior de un rango desde ese valor hasta el doble de ese valor y el número de la derecha es el número de archivos en ese rango.
Basado en la respuesta de garyjohn, aquí hay una línea, que también formatea la salida para que sea legible por humanos:
find . -type f -print0 | xargs -0 ls -l | awk '{ n=int(log($5)/log(2)); if (n<10) { n=10; } size[n]++ } END { for (i in size) printf("%d %d\n", 2^i, size[i]) }' | sort -n | awk 'function human(x) { x[1]/=1024; if (x[1]>=1024) { x[2]++; human(x) } } { a[1]=$1; a[2]=0; human(a); printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }'
Aquí está la versión ampliada:
find . -type f -print0 \
| xargs -0 ls -l \
| awk '{ n=int(log($5)/log(2)); \
if (n<10) n=10; \
size[n]++ } \
END { for (i in size) printf("%d %d\n", 2^i, size[i]) }' \
| sort -n \
| awk 'function human(x) { x[1]/=1024; \
if (x[1]>=1024) { x[2]++; \
human(x) } } \
{ a[1]=$1; \
a[2]=0; \
human(a); \
printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }'
En el primer awk
Definí un tamaño de archivo mínimo para recopilar todos los archivos de menos de 1 kb en un solo lugar. En el segundo awk
, función human(x)
se define para crear un tamaño legible por humanos. Esta parte se basa en una de las respuestas aquí:https://unix.stackexchange.com/questions/44040/a-standard-tool-to-convert-a-byte-count-into-human-kib-mib-etc -como-du-ls1
La salida de muestra se parece a:
1k: 335
2k: 16
32k: 5
128k: 22
1M: 54
2M: 11
4M: 13
8M: 3
Prueba esto:
find . -type f -exec ls -lh {} \; |
gawk '{match($5,/([0-9.]+)([A-Z]+)/,k); if(!k[2]){print "1K"} \
else{printf "%.0f%s\n",k[1],k[2]}}' |
sort | uniq -c | sort -hk 2
SALIDA:
38 1K
14 2K
1 30K
2 62K
12 2M
2 3M
1 31M
1 46M
1 56M
1 75M
1 143M
1 191M
1 246M
1 7G
EXPLICACIÓN:
-
find . -type f -exec ls -lh {} \;
:bastante simple, busque archivos en el directorio actual y ejecutels -lh
en ellos -
match($5,/([0-9.]+)([A-Z]+)/,k);
:esto extraerá el tamaño del archivo y guardará cada coincidencia en la matrizk
. -
if(!k[2]){print "1K"}
:sik[2]
no está definido, el tamaño del archivo es <1K. Como imagino que no te importan los tamaños tan pequeños, el script imprimirá1K
para todos los archivos cuyo tamaño sea <=1K. -
else{printf "%.0f%s\n",k[1],k[2]}
:si el archivo tiene más de 1K, redondee el tamaño del archivo al entero más cercano e imprímalo junto con su modificador (K, M o G). -
sort | uniq -c
:cuente las ocurrencias de cada línea (tamaño de archivo) impresa. -
sort -hk 2
:ordenar según el segundo campo en formato legible por humanos. De esta manera,7G
se ordena después de8M
.