Renommer ses photos en masse… en Python
Ou comment découvrir que des notions en programmation peuvent vous faciliter le quotidien…
Mais on va quand même éviter toute confusion : cet article ne propose pas une solution plus simple que mon précédent article Renommer ses photos en masse avec Exiftool. Ici, je vais vous montrer comment faire plein de choses que Exiftool fait pour vous. Pourquoi réécrire ce que fait Exiftool ? Simplement pour pouvoir faire plus que ce que vous propose ce logiciel.

Cet article est est donc la première étape vers une automatisation de votre gestion de photos.
Cet article n’a pas non plus pour but d’initier un néophyte à la programmation. Je pense avoir rendu les grandes lignes accessibles pour que vous puissiez voir ce que l’on peut faire et peut-être éveiller votre intérêt. Si vous avez déjà des notions, l’exemple ci-dessous n’est pas un exemple complet clef-en-main. L’objectif est de vous montrer que si vous avez la possibilité de donner vous même des instructions à votre ordinateur, vous pourrez adapter l’exécution à votre besoin.
Pourquoi Python ?
Pour donner des instructions à un ordinateur, il faut choisir un langage. Je ne vais pas m’étendre sur les différences entre eux et je vais faire simple : Python est un langage facile à apprendre et à mettre en pratique. Il est disponible sur toutes les plate-formes (Linux, Mac et même Windows). Python dispose d’une forte communauté qui fait vivre le langage et lui apporte de nouvelles fonctionnalités comme celles que nous allons voir. Enfin, ces caractéristiques font de Python le langage aujourd’hui le plus adapté à l’enseignement de la programmation.
Rappel : lister les fichiers en Python
Nous souhaitons récupérer la liste des fichiers du répertoire courant. Pour ce faire, en Python, il y a deux manières : soit en utilisant la fonction listdir du module os, soit en utilisant la fonction glob du module glob. La seconde permet de filtrer les fichiers par des motifs (par exemple uniquement les fichiers avec l’extension CR2). Comme je ne souhaite récupérer que les fichiers RAW issus de mon appareil, je vais utiliser la fonction glob :
import glob image_files = glob.glob('*.CR2')
Si votre répertoire contient des fichiers image avec plusieurs types d’extension et que vous souhaitez tous les charger, cela va être un peu plus complexe (et nous permet d’utiliser les listes en intension 🙂 ) :
import os image_ext = ['.jpg', '.jpeg', '.JPG', '.JPEG'] image_files = [f for f in os.listdir('.') if os.path.splitext(f)[1] in image_ext]
L’instruction os.path.splitext(f)[1] mérite peut-être quelques explications et vous allez voir que si vous comprenez ce que retourne chaque expression, c’est finalement tout simple.
La fonction splitext() du module os.path prend en paramètre une chaine de caractères représentant un nom de fichier ou un chemin et retourne un tuple (c’est similaire à une liste) contenant deux éléments : le nom original sans l’extension et l’extension.
>>> import os.path >>> os.path.splitext("mon_image.jpg") ("mon_image", ".jpg") >>> os.path.splitext("mon_repertoire/mon_image.jpg") ("mon_repertoire/mon_image", ".jpg")
Pour connaitre l’extension, nous ne souhaitons utiliser que le second élément, donc celui à l’indice 1. os.path.splitext(f)[1] retourne donc une chaine de caractères contenant l’extension.
Astuce : si la liste image_ext est redondante, c’est parce que Python est sensible à la casse. Donc jpg est différent de JPG. Plutôt que de lister tous les cas de figure, le principe est d’uniformiser la casse des chaines à comparer. Vous pouvez donc déclarer une liste d’extensions en minuscules et convertir le résultat du fichier lu par la méthode lower().
import os image_ext = ['.jpg', '.jpeg'] image_files = [f for f in os.listdir('.') if os.path.splitext(f)[1].lower() in image_ext]
Rappel : renommer les fichiers en Python
Renommer un fichier en Python se fait avec la fonction rename() du module os. Les deux paramètres sont évidemment le nom du fichier à renommer et le nom attendu :
import os os.rename('mon_ancien_nom.txt', 'mon_nouveau_nom.txt')
Attention cependant, si un fichier portant le nom tel qu’il sera renommé existe, sur Linux ou Mac OS, il sera écrasé, sous Windows, cela provoquera une erreur. Il est donc plus prudent de vérifier l’existence d’un fichier avec le nom de destination avant de procéder à un renommage.
import os if not os.path.exists('mon_nouveau_nom.txt'): os.rename('mon_ancien_nom.txt', 'mon_nouveau_nom.txt')
Récupérer la date de prise de vue
Je souhaite renommer mes fichiers photo en fonction de leur date de prise de vue. Celle-ci est contenue dans les données Exif du fichier photo. Pour lire ces données Exif, nous allons utiliser une librairie externe : ExifRead. Le lien explique comment installer cette dépendance.
ExifRead permet de charger toutes les données Exif sous forme d’un dictionnaire. Nous allons pouvoir récupérer la date à l’aide de sa clef, « EXIF DateTimeOriginal« . Cette date, si elle existe, est présente sous la forme d’une chaine de caractère qu’il sera possible de lire afin de créer un objet du type datetime. Le format correspond au motif ‘%Y:%m:%d %H:%M:%S’. Nous allons donc avoir :
import exifread from datetime import datetime with open('mon_image.CR2', 'rb') as my_picture: tags = exifread.process_file(my_picture) try: picture_date = datetime.strptime(str( tags.get('EXIF DateTimeOriginal')), '%Y:%m:%d %H:%M:%S') except ValueError: picture_date = None print("No value for %s" % filename)
Dans cet exemple de code, l’absence de la donnée Exif ou un mauvais format de date est gérée par une exception. Là je vous laisse libre de faire ce que vous voulez. La variable picture_date contient un objet de type datetime qui va nous faciliter la manipulation de la date de prise de vue et notamment la génération du nom de fichier de sortie. Le format que j’utilise est définit par le motif ‘%y%m%d-%H%M%S’. Celui-ci est passé en paramètre à la méthode strftime.
Renommer le fichier
Grâce au code précédent, je peux donc créer le nom du fichier de destination et procéder à la copie pour les fichier dont j’ai pu récupérer une date par les instructions suivantes :
import os if picture_date: rename_name = picture_date.strftime('%y%m%d-%H%M%S') + '.CR2' if not os.path.exists(rename_name): os.rename('mon_image.CR2', rename_name)
Vous avez maintenant de quoi écrire votre propre programme pour renommer vos photos. Je vous propose pour ma part sur mon Github un exemple de mise en œuvre basé sur cet article.
Reste la question de pourquoi tout ça alors que nous avons des logiciels qui le font déjà ? Pour deux raisons présentées dans la partie suivante.
Apprenez et développez
L’aspect pédagogique
Même si ce billet n’est pas un cours complet de Python, l’aspect pédagogique est la raison pour laquelle je détaille certaines notions. Nous avons vu comment :
- obtenir la liste des fichiers d’un répertoire et en particulier, comment n’obtenir que certains fichiers
- utiliser une librairie externe
- extraire des informations de ces fichiers et en particulier une métadonnée d’un fichier image
- transformer cette donnée pour un autre usage, ici générer un nom pour renommer le fichier
- effectuer quelques contrôles afin d’éviter les incidents.
Une première brique
Lorsqu’on écrit quelques lignes de code, c’est pour se faciliter la vie. Mais c’est aussi pour pouvoir les réutiliser pour autre chose. Sur la base de ce code, nous avons la possibilité d’exploiter d’autres métadonnées de la prise de vue. Mais nous avons aussi la possibilité d’exploiter cette métadonnée pour autre chose. Et si nous en profitions pour ranger automatiquement ces photos ? Ça va être très intéressant mais… Pour un prochain billet 😉
À propos de... Darko Stankovski
iT guy, photographe et papa 3.0, je vous fais partager mon expérience et découvertes dans ces domaines. Vous pouvez me suivre sur les liens ci-dessous.
2 réponses
[…] mon article précédent, pour renommer nos photos en Python, il était nécessitait d’extraire l’information de la date de prise de vue. Tant que nous […]
[…] vous ai proposé un article sur comment renommer vos photos avec Python. Le code que je vous ai proposé dans l’article et qui est disponible sur mon Github, […]