Kann ich ein Du nach Monat gruppieren lassen?

14

Ich habe ein Verzeichnis mit vielen Fotos. Speziell du -sh --apparent-size /path/to/myfoldergibt mir 331G. Was toll ist. Aber jetzt möchte ich eine nach Monaten gruppierte Auflistung bekommen, zB so etwas:

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

Gibt es eine (vernünftige) Möglichkeit, dies unter Linux zu tun, oder sollte ich einfach mein eigenes Python-Dienstprogramm schreiben, um dies zu tun?

Wayne Werner
quelle
1
Linux hat keine eingebauten Komponenten , es ist ein Betriebssystemkernel. Meinen Sie mit den Befehlen, die standardmäßig in einigen Linux-basierten Betriebssystemen (wie Debian, Fedora, ChromeOS ...) vorkommen ?
Stéphane Chazelas
8
Der Linux-Kernel ist der Linux-Kernel, und wenn ich gemeint hätte, dass der Linux-Kernel eingebaut ist, hätte ich das gesagt. Wenn Sie müssen pedantisch sein, ich meine den allgemeinen Satz von Werkzeugen , dass Sie statistisch wahrscheinlich mit einer Standardinstallation von einem der Top - 5 - Linux - Distributionen installiert haben.
Wayne Werner
1
@WayneWerner Mit anderen Worten, Sie meinen GNU / Linux, einschließlich Bash, Coreutils und anderen Kernkomponenten der GNU-Betriebsumgebung. #rmswasright
Damian Yerrick

Antworten:

23

Versuchen Sie unter 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

Wie es funktioniert

  • find /my/path

    Dies sucht nach Dateien in / my / path.

  • -maxdepth 1

    Dies weist an, findnicht in Unterverzeichnisse zu schauen. (Wenn Sie eine rekursive Suche wünschen, lassen Sie diese Option aus.)

  • -type f

    Dadurch wird finddie Suche auf reguläre Dateien beschränkt.

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

    Dies teilt findmit, dass Jahr-Monat gefolgt von der Größe in Bytes für jede Datei gedruckt werden soll.

    Da wir keine Verwendung für sie haben, werden die Namen der gefundenen Dateien nicht gedruckt.

  • b[$1]+=$2

    Für jede gefundene Datei addieren wir die Anzahl der gefundenen Bytes aus Spalte 2 zu der Anzahl dieser Jahr-Monat-Kombination im assoziativen Array b.

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

    Nachdem wir die gesamte Ausgabe von verarbeitet haben find, drucken wir die Ergebnisse aus.

  • sort

    Dadurch werden die Ergebnisse in der Reihenfolge des Datums sortiert.

Mehrzeilige Version

Für diejenigen, die ihren Code auf mehrere Zeilen verteilen möchten:

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

Beispiel

Betrachten wir ein Verzeichnis mit diesen Dateien:

$ 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

Die Ausgabe unseres Befehls lautet:

$ 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

Verfeinerungen

Wenn die Ausgabe in Mebibyte (MiB) statt in Bytes erfolgen soll, können wir die Einheiten folgendermaßen konvertieren:

$ 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

Mit können wir das Ausgabeformat noch besser steuern printf. Um nur eine Stelle nach dem Komma zu behalten, formatieren wir die Größe mit %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
quelle
Das ist fantastisch. Können Sie awk-Tutorials empfehlen? Ich habe noch keinen gefunden, der meine Augen nicht innerhalb von etwa zwanzig Sekunden gekreuzt hat.
hBy2Py
1
@ hBy2Py Meine Lieblingseinführung in awk ist das Grymoire-Tutorial , obwohl es jetzt ein bisschen veraltet ist .
John1024
Ich schlage vor, printf "%s %9d\n", date, b[date]anstelle vonprint date, b[date] Leerzeichen in der zweiten Spalte
hinzuzufügen
Gute Idee. Ich habe gerade die Antwort mit einem Beispiel aktualisiert, das verwendetprintf .
John1024
FWIW, wenn Sie finddiese Unterstützung haben , haben -maxdepthSie wahrscheinlich[g]awk diese UnterstützungPROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085