Cómo encontrar el tamaño de archivo total agrupado por extensión

12

Trabajo en un clúster compartido con otros colegas. El disco duro es limitado (y ha estado lleno en algunas ocasiones), así que ocasionalmente limpio mi parte. Quiero hacer esto rápidamente, así que hasta ahora lo hago haciendo una lista de archivos de más de 100 MB de más de 3 meses, y veo si todavía los necesito.

Pero ahora estoy pensando que podría haber una carpeta con> 1000 archivos más pequeños que echo de menos, así que quiero obtener una manera fácil de ver si este es el caso. Por la forma en que genero datos, sería útil obtener una lista del tamaño total por extensión. En el contexto de esta pregunta, 'extensión' como todo lo que está detrás del último punto en el nombre del archivo.

Supongamos que tengo varias carpetas con múltiples archivos:

folder1/file1.bmp   40 kiB
folder1/file2.jpg   20 kiB
folder2/file3.bmp   30 kiB
folder2/file4.jpg    8 kiB

¿Es posible hacer una lista del tamaño total de archivos por extensión de archivo, así:

bmp 70 kiB
jpg 28 kiB

No me importan los archivos sin extensión, por lo que pueden ignorarse o colocarse en una categoría.

Ya revisé las páginas de manual de ls, duy find, pero no sé cuál es la herramienta adecuada para este trabajo ...

contramodo
fuente
Esta pregunta no estaría mal en codegolf.stackexchange.com :)
Doug McLean
@DougMcLean: puedes publicarlo allí. ;)

Respuestas:

16

En un sistema GNU:

find . -name '?*.*' -type f -printf '%b.%f\0' |
  awk -F . -v RS='\0' '
    {s[$NF] += $1; n[$NF]++}
    END {for (e in s) printf "%15d %4d %s\n", s[e]*512, n[e], e}' |
  sort -n

O lo mismo con perl, evitando la -printfextensión de GNU find(todavía usando una extensión de GNU -print0, pero esta es más ampliamente compatible hoy en día):

find . -name '?*.*' -type f -print0 |
  perl -0ne '
    if (@s = stat$_){
      ($ext = $_) =~ s/.*\.//s;
      $s{$ext} += $s[12];
      $n{$ext}++;
    }
    END {
      for (sort{$s{$a} <=> $s{$b}} keys %s) {
        printf "%15d %4d %s\n",  $s{$_}<<9, $n{$_}, $_;
      }
    }'

Da una salida como:

          12288    1 pnm
          16384    4 gif
         204800    2 ico
        1040384   17 jpg
        2752512   83 png

Si quieres KiB, MiB... sufijos, pipa a numfmt --to=iec-i --suffix=B.

%b*512proporciona el uso del disco, pero tenga en cuenta que si los archivos están vinculados varias veces, se contarán varias veces para que pueda ver una discrepancia con los duinformes.

Stéphane Chazelas
fuente
Falla en MacOS (buscar: -printf: primario u operador desconocido)
MichaelCodes
1
@MichaelCodes, sí, -printfes específico de GNU find, por eso lo dije en un sistema GNU .
Stéphane Chazelas
@MichaelCodes, vea editar con una perlalternativa que debería funcionar incluso en macOS.
Stéphane Chazelas
¿Qué es 1,4,2,17? ¿La cantidad de archivos para cada tipo?
Jorge Cornejo Bellido
3

Aquí hay otra solución:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \; | egrep "^\.[a-zA-Z0-9]+$|total$" | uniq | paste - -

La parte que obtiene las extensiones es:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u

Luego busque los archivos con una extensión e imprímalos también en la pantalla:

xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \;

A continuación queremos mantener la extensión y el total:

egrep "^\.[a-zA-Z0-9]+$|total$" | uniq

y mantenlo en la misma línea:

paste - -
vahbuna
fuente
Funciona en MacOS.
MichaelCodes
2

No es tan bueno como la solución de Stephane, pero podrías intentar

find . -type f -name "*.png" -print0 | xargs -0r du -ch | tail -n1

donde debe ejecutar esto para cada tipo de archivos.

contramodo
fuente
1
Eso supone que hay suficientes archivos png que solo duse ejecuta una invocación. Con GNU xargs, desearía agregar el -rindicador para que no se ejecute cuando no hay archivo (de lo contrario, terminaría con el uso del disco del directorio actual). Es posible que desee agregar un -type fo ! type dpara evitar contar los archivos que están en directorios cuyo nombre termina en .png.
Stéphane Chazelas
esto solo busca una extensión específica.
Rahul
Eso es lo que escribí. Uno tenía que envolverlo en un script que itera sobre todas las extensiones aplicables para obtener una solución "completa".
contramode