Puis-je obtenir un `du` groupé par mois?

14

J'ai un répertoire contenant beaucoup de photos. Plus précisément, du -sh --apparent-size /path/to/myfolderme donne 331G. Qui est genial. Mais maintenant, je veux obtenir une liste groupée par mois, par exemple quelque chose comme ceci:

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

Existe-t-il un moyen (raisonnable) de le faire avec les extensions Linux, ou dois-je simplement écrire mon propre utilitaire Python pour le faire?

Wayne Werner
la source
1
Linux n'a pas de intrinsèques , c'est un noyau de système d'exploitation. Voulez-vous dire avec les commandes trouvées par défaut dans certains systèmes d'exploitation basés sur Linux (comme Debian, Fedora, ChromeOS ...) à la place?
Stéphane Chazelas
8
Le noyau Linux est le noyau linux, et si je voulais dire les noyaux intégrés au noyau linux, je l'aurais dit. Si vous devez être pédant, je veux dire l'ensemble général d'outils que vous êtes statistiquement susceptible d'avoir installé avec une installation par défaut de l'une des 5 meilleures distributions Linux.
Wayne Werner
1
@WayneWerner En d'autres termes, vous voulez dire GNU / Linux, y compris Bash, Coreutils et d'autres composants de base de l'environnement d'exploitation GNU. #rmswasright
Damian Yerrick

Réponses:

23

Sur Linux, essayez:

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

Comment ça fonctionne

  • find /my/path

    Cela recherche les fichiers dans / mon / chemin.

  • -maxdepth 1

    Cela indique de findne pas regarder dans les sous-répertoires. (Si vous souhaitez une recherche récursive, omettez cette option.)

  • -type f

    Cela indique findde limiter la recherche aux fichiers normaux.

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

    Cela indique findd'imprimer l'année-mois suivi de la taille en octets pour chaque fichier.

    Comme nous ne les utilisons pas, les noms des fichiers trouvés ne sont pas imprimés.

  • b[$1]+=$2

    Pour chaque fichier trouvé, nous ajoutons son nombre d'octets, trouvé dans la colonne 2, au nombre de cette combinaison année-mois dans le tableau associatif b.

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

    Après avoir traité toutes les sorties de find, nous imprimons les résultats.

  • sort

    Cela trie les résultats par ordre de date.

Version à plusieurs lignes

Pour ceux qui préfèrent leur code étalé sur plusieurs lignes:

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

Exemple

Prenons un répertoire avec ces fichiers:

$ 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

La sortie de notre commande est:

$ 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

Raffinements

Si nous voulons la sortie en mégaoctets (MiB) au lieu d'octets, nous pouvons convertir les unités comme ceci:

$ 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

Nous pouvons obtenir encore plus de contrôle sur le format de sortie en utilisant printf. Ici, pour ne conserver qu'un chiffre après le point décimal, nous formaterons la taille avec %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
la source
C'est fantastique. Pouvez-vous recommander des tutoriels awk? Je n'en ai pas encore trouvé un qui ne m'ait pas traversé les yeux en une vingtaine de secondes.
hBy2Py
1
@ hBy2Py Mon introduction préférée à awk, même si elle est maintenant un peu datée, est le tutoriel Grymoire .
John1024
je suggère d'utiliser printf "%s %9d\n", date, b[date]au lieu de print date, b[date]pour ajouter un remplissage d'espace à la deuxième colonne
rav_kr
@rav_kr Bonne idée. Je viens de mettre à jour la réponse avec un exemple qui utilise printf.
John1024
FWIW si vous avez findque des supports -maxdepthvous probablement avoir [g]awkque des supportsPROC_INFO["sorted_in"]="@ind_str_asc"
dave_thompson_085