¿Puedo obtener un `du` agrupado por mes?

14

Tengo un directorio con muchas fotos. Específicamente, du -sh --apparent-size /path/to/myfolderme da 331G. Lo cual es genial. Pero ahora quiero obtener una lista agrupada por mes, por ejemplo, algo como esto:

2016-01   20MB
2016-02  520MB
2016-03  312MB
...

¿Hay una manera (razonable) de hacer esto con linux builtins, o debería escribir mi propia utilidad Python para hacerlo?

Wayne Werner
fuente
1
Linux no tiene incorporados , es un núcleo del sistema operativo. ¿Te refieres a los comandos que se encuentran por defecto en algunos sistemas operativos basados ​​en Linux (como Debian, Fedora, ChromeOS ...) en su lugar?
Stéphane Chazelas
8
El kernel de Linux es el kernel de Linux, y si quisiera decir que el kernel de Linux está integrado, lo habría dicho. Si debe ser pedante, me refiero al conjunto general de herramientas que estadísticamente es probable que haya instalado con una instalación predeterminada de cualquiera de las 5 principales distribuciones de Linux.
Wayne Werner
1
@WayneWerner En otras palabras, se refiere a GNU / Linux, incluidos Bash, Coreutils y otros componentes centrales del entorno operativo GNU. #rmswasright
Damian Yerrick

Respuestas:

23

En Linux, intente:

find /my/path -maxdepth 1 -type f -printf '%TY-%Tm %s\n' | awk '{b[$1]+=$2} END{for (date in b) print date, b[date]}' | sort

Cómo funciona

  • find /my/path

    Esto busca archivos en / my / path.

  • -maxdepth 1

    Esto le dice que findno busque en subdirectorios. (Si desea una búsqueda recursiva, omita esta opción).

  • -type f

    Esto le indica findque limite la búsqueda a archivos normales.

  • -printf '%TY-%Tm %s\n'

    Esto le indica findque imprima año-mes seguido del tamaño en bytes para cada archivo.

    Como no los usamos, los nombres de los archivos encontrados no se imprimen.

  • b[$1]+=$2

    Para cada archivo encontrado, agregamos su recuento de bytes, encontrado en la columna 2, al recuento de esa combinación año-mes en una matriz asociativa b.

  • END{for (date in b) print date, b[date]}

    Después de haber procesado toda la salida find, imprimimos los resultados.

  • sort

    Esto ordena los resultados en orden de fecha.

Versión de línea múltiple

Para aquellos que prefieren su código distribuido en varias líneas:

find /my/path -maxdepth 1 -type f -printf '%TY-%Tm %s\n' |
  awk '
    {
      b[$1]+=$2
    }

    END{
      for (date in b)
        print date, b[date]
    }
    ' | sort

Ejemplo

Consideremos un directorio con estos archivos:

$ ls -l
total 27816
-rw------- 1 john1024 john1024 2459173 Nov 23  2015 img100.jpg
-rw------- 1 john1024 john1024 3479750 Nov 23  2015 img101.jpg
-rw------- 1 john1024 john1024 4028939 Nov 23  2015 img102.jpg
-rw------- 1 john1024 john1024 2928519 Jul 30 18:55 img103.jpg
-rw------- 1 john1024 john1024 2948294 Jul 30 18:55 img104.jpg
-rw------- 1 john1024 john1024 3177583 Aug  1 16:56 img105.jpg
-rw-rw---- 1 john1024 john1024 3111737 Apr 18  2016 img106.jpg
-rw-rw---- 1 john1024 john1024 1441310 Apr 18  2016 img107.jpg
-rw-rw---- 1 john1024 john1024 2430158 Apr 25 16:26 img108.jpg
-rw-rw---- 1 john1024 john1024 2424504 Apr 25 16:26 img109.jpg

El resultado de nuestro comando es:

$ find . -maxdepth 1 -type f -printf '%TY-%Tm %s\n' | awk '{b[$1]+=$2} END{for (date in b) print date, b[date]}' | sort
2015-11 9967862
2016-04 9407709
2016-07 5876813
2016-08 3177583

Refinamientos

Si queremos la salida en mebibytes (MiB) en lugar de bytes, podemos convertir las unidades de esta manera:

$ find . -maxdepth 1 -type f -printf '%TY-%Tm %s\n' | awk '{b[$1]+=$2} END{for (date in b) print date, b[date]/1024**2, "MiB"}' | sort
2015-11 9.50609 MiB
2016-04 8.97189 MiB
2016-07 5.60457 MiB
2016-08 3.03038 MiB

Podemos obtener aún más control sobre el formato de salida mediante el uso printf. Aquí, para mantener solo un dígito después del punto decimal, formateamos el tamaño con %5.1f:

$ find . -maxdepth 1 -type f -printf '%TY-%Tm %s\n' | awk '{b[$1]+=$2} END{for (date in b) printf "%s %5.1f MiB\n", date, b[date]/1024**2}' | sort
2015-11   9.5 MiB
2016-04   9.0 MiB
2016-07   5.6 MiB
2016-08   3.0 MiB
John1024
fuente
Esto es fantástico. ¿Me puede recomendar algún tutorial de awk? Todavía no he encontrado uno que no haya cruzado mis ojos en unos veinte segundos.
hBy2Py
1
@ hBy2Py Mi introducción favorita a awk, aunque ahora está un poco anticuada, es el tutorial de Grymoire .
John1024
sugiero usar en printf "%s %9d\n", date, b[date]lugar de print date, b[date]agregar relleno de espacio a la segunda columna
rav_kr
@rav_kr Buena idea. Acabo de actualizar la respuesta con un ejemplo que usa printf.
John1024
Fwiw si tiene findque apoya -maxdepthque probablemente tenga [g]awkque soportesPROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085