Posso agrupar um du por mês?

14

Eu tenho um diretório com muitas fotos nele. Especificamente, du -sh --apparent-size /path/to/myfolderme dá 331G. O que é ótimo. Mas agora eu quero obter uma listagem agrupada por mês, por exemplo, algo como isto:

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

Existe uma maneira (razoável) de fazer isso com os linux builtins, ou devo apenas escrever meu próprio utilitário Python para fazer isso?

Wayne Werner
fonte
1
O Linux não possui built-in , é um kernel do sistema operacional. Você quer dizer com os comandos encontrados por padrão em alguns sistemas operacionais baseados em Linux (como Debian, Fedora, ChromeOS ...) ?
Stéphane Chazelas
8
O kernel do Linux é o kernel do linux, e se eu quisesse dizer sobre os kernel do linux, eu diria isso. Se você deve ser pedante, quero dizer o conjunto geral de ferramentas que você está estatisticamente provável que tenha instalados com uma instalação padrão de qualquer um dos top 5 distribuições Linux.
Wayne Werner
1
@WayneWerner Em outras palavras, você quer dizer GNU / Linux, incluindo Bash, Coreutils e outros componentes principais do ambiente operacional GNU. #rmswasright
Damian Yerrick

Respostas:

23

No Linux, tente:

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

Como funciona

  • find /my/path

    Isso procura por arquivos em / my / path.

  • -maxdepth 1

    Isso diz findpara não procurar subdiretórios. (Se você deseja uma pesquisa recursiva, omita essa opção.)

  • -type f

    Isso diz findpara limitar a pesquisa a arquivos regulares.

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

    Isto indica findpara imprimir o ano-mês seguido pelo tamanho em bytes para cada arquivo.

    Como não temos utilidade para eles, os nomes dos arquivos encontrados não são impressos.

  • b[$1]+=$2

    Para cada arquivo encontrado, adicionamos sua contagem de bytes, encontrada na coluna 2, à contagem daquela combinação ano-mês na matriz associativa b.

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

    Depois de processarmos toda a saída find, imprimimos os resultados.

  • sort

    Isso classifica os resultados em ordem de data.

Versão de várias linhas

Para aqueles que preferem seu código espalhado por várias linhas:

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

Exemplo

Vamos considerar um diretório com esses arquivos:

$ 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

A saída do nosso comando é:

$ 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

Refinamentos

Se queremos a saída em mebibytes (MiB) em vez de bytes, podemos converter as unidades assim:

$ 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 obter ainda mais controle sobre o formato de saída usando printf. Aqui, para manter apenas um dígito após o ponto decimal, formata-se o tamanho com %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
fonte
Isto é fantástico. Você pode recomendar algum tutorial do awk? Ainda não encontrei uma que não fiz meus olhos se cruzarem em cerca de vinte segundos.
Hby2Py 18/10
1
@ hBy2Py Minha introdução favorita ao awk, embora agora esteja um pouco desatualizada, é o tutorial do Grymoire .
John1024
Eu sugiro usar printf "%s %9d\n", date, b[date]em vez de print date, b[date]adicionar preenchimento de espaço para a segunda coluna
rav_kr
@rav_kr Boa ideia. Acabei de atualizar a resposta com um exemplo que usa printf.
John1024
FWIW, se você tem findque suporta -maxdepthvocê provavelmente tem [g]awkque suportesPROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085