Могу ли я сгруппировать 'du` по месяцам?

14

У меня есть каталог с большим количеством фотографий. Конкретно, du -sh --apparent-size /path/to/myfolderдает мне 331G. Что здорово. Но теперь я хочу получить список сгруппированных по месяцам, например, примерно так:

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

Есть (разумный) способ сделать это с помощью встроенных в Linux, или мне просто написать свою собственную утилиту Python, чтобы сделать это?

Уэйн Вернер
источник
1
У Linux нет встроенных функций , это ядро ​​операционной системы. Вы имеете в виду команды, найденные по умолчанию в некоторых операционных системах на основе Linux (например, Debian, Fedora, ChromeOS ...) ?
Стефан Шазелас
8
Ядро Linux - это ядро ​​Linux, и если бы я имел в виду встроенное ядро ​​Linux, я бы сказал это. Если вы, должно быть, педантичны, я имею в виду общий набор инструментов, которые вы, по статистике, вероятно, установили при установке по умолчанию любого из 5 лучших дистрибутивов Linux.
Уэйн Вернер
1
@WayneWerner Другими словами, вы имеете в виду GNU / Linux, включая Bash, Coreutils и другие основные компоненты операционной среды GNU. #rmswasright
Дамиан Йеррик

Ответы:

23

В Linux попробуйте:

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

Как это устроено

  • find /my/path

    Это ищет файлы в / my / path.

  • -maxdepth 1

    Это говорит findне смотреть в подкаталоги. (Если вы хотите рекурсивный поиск, пропустите эту опцию.)

  • -type f

    Это говорит findоб ограничении поиска обычными файлами.

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

    Это говорит findо том, что нужно распечатать год-месяц с указанием размера в байтах для каждого файла.

    Поскольку мы их не используем, имена найденных файлов не печатаются.

  • b[$1]+=$2

    Для каждого найденного файла мы добавляем его количество байтов, найденное в столбце 2, к количеству этой комбинации год-месяц в ассоциативном массиве b.

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

    После того, как мы обработали все выходные данные find, мы распечатываем результаты.

  • sort

    Это сортирует результаты по дате.

Многострочная версия

Для тех, кто предпочитает их код в несколько строк:

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

пример

Давайте рассмотрим каталог с этими файлами:

$ 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

Вывод нашей команды:

$ 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

Уточнения

Если мы хотим получить выходные данные в мегабайтах (MiB) вместо байтов, мы можем преобразовать единицы следующим образом:

$ 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

Мы можем получить еще больший контроль над форматом вывода с помощью printf. Здесь, чтобы сохранить только одну цифру после десятичной точки, мы форматируем размер с помощью %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
источник
Это фантастика. Можете ли вы порекомендовать какие-либо учебники по awk? Я еще не нашел тот, который не заставил бы мои глаза скреститься в течение двадцати секунд.
hBy2Py
1
@ hBy2Py Мое любимое введение в awk, хотя оно и устарело , - это учебник Grymoire .
John1024
я предлагаю использовать printf "%s %9d\n", date, b[date]вместо того, print date, b[date]чтобы добавить пробел во второй столбец
rav_kr
@rav_kr Хорошая идея. Я только обновил ответ с примером, который использует printf.
John1024
FWIW, если у вас есть findэта поддержка, у -maxdepthвас, вероятно, есть [g]awkподдержкаPROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085