Czy mogę uzyskać du zgrupowane według miesięcy?

14

Mam katalog z dużą ilością zdjęć. Konkretnie du -sh --apparent-size /path/to/myfolderdaje mi 331G. Który jest świetny. Ale teraz chcę uzyskać listę pogrupowaną według miesięcy, np. Coś takiego:

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

Czy istnieje (rozsądny) sposób, aby to zrobić za pomocą wbudowanych linuksów, czy powinienem po prostu napisać własne narzędzie Python, aby to zrobić?

Wayne Werner
źródło
1
Linux nie ma wbudowanych , jest jądrem systemu operacyjnego. Czy masz na myśli polecenia, które domyślnie znajdują się w niektórych systemach operacyjnych opartych na Linuksie (takich jak Debian, Fedora, ChromeOS ...) ?
Stéphane Chazelas
8
Jądro Linuksa jest jądrem Linuksa, a gdybym miał na myśli wbudowane jądro Linuksa, powiedziałbym to. Jeśli musisz być pedantyczny, mam na myśli ogólny zestaw narzędzi, które statystycznie prawdopodobnie zainstalowałbyś z domyślną instalacją jednego z 5 najlepszych dystrybucji Linuksa.
Wayne Werner
1
@WayneWerner Innymi słowy, masz na myśli GNU / Linux, w tym Bash, Coreutils i inne podstawowe komponenty środowiska operacyjnego GNU. #rmswasright
Damian Yerrick

Odpowiedzi:

23

W systemie Linux spróbuj:

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

Jak to działa

  • find /my/path

    Wyszukuje pliki w / my / path.

  • -maxdepth 1

    Mówi findto, aby nie zaglądać do podkatalogów. (Jeśli chcesz wyszukać rekurencyjnie, pomiń tę opcję).

  • -type f

    Oznacza findto ograniczenie wyszukiwania do zwykłych plików.

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

    Mówi o tym, findaby wydrukować rok-miesiąc, a następnie rozmiar w bajtach dla każdego pliku.

    Ponieważ nie używamy ich, nazwy znalezionych plików nie są drukowane.

  • b[$1]+=$2

    Dla każdego znalezionego pliku dodajemy jego liczbę bajtów, znalezioną w kolumnie 2, do liczby, którą ta kombinacja rok-miesiąc w tablicy asocjacyjnej b.

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

    Po przetworzeniu wszystkich danych wyjściowych finddrukujemy wyniki.

  • sort

    To sortuje wyniki według daty.

Wersja wieloliniowa

Dla tych, którzy wolą kod rozłożony na wiele wierszy:

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

Przykład

Rozważmy katalog z tymi plikami:

$ 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

Dane wyjściowe z naszego polecenia to:

$ 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

Udoskonalenia

Jeśli chcemy, aby dane wyjściowe były w bajtach (MiB) zamiast w bajtach, możemy przekonwertować jednostki w następujący sposób:

$ 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

Za pomocą możemy uzyskać jeszcze większą kontrolę nad formatem wyjściowym printf. Tutaj, aby zachować tylko jedną cyfrę po przecinku, formatujemy rozmiar za pomocą %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
źródło
To jest fantastyczne. Czy możesz polecić jakieś tutoriale awk? Nie znalazłem jeszcze takiego, który nie sprawiłby, żebym spojrzał mi w oczy w ciągu około dwudziestu sekund.
hBy2Py 18.10.16
1
@ hBy2Py Moim ulubionym wprowadzeniem do awk, choć jest już trochę przestarzałe, jest samouczek Grymoire .
John1024,
Sugeruję użycie printf "%s %9d\n", date, b[date]zamiast print date, b[date]dodawania spacji do drugiej kolumny
rav_kr
@rav_kr Dobry pomysł. Właśnie zaktualizowałem odpowiedź za pomocą przykładu, który wykorzystuje printf.
John1024,
FWIW, jeśli masz findwsparcie -maxdepth, prawdopodobnie masz [g]awkwsparciePROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085,