Renommer les photos par lot en utilisant les métadonnées EXIF

Dessin laptop avec une loupe où il est écrit "Tuto"

Renommer des photos par lot en utilisant les données EXIF de chaque image.

Ou comment avoir un nom ressemblant à « 2010-0613-16h07m08s-chantier.JPG » au lieu de « DSC_0005.JPG »

Prérequis:
« exiv2 » doit être installé.
On va utiliser les commandes « find » et « exiv2  »

Voyons ce qu’il y a dans le répertoire courant:

$ ls
DSC_0005.JPG DSC_0006.JPG DSC_0007.JPG DSC_0008.JPG

On va renommer les photos en utilisant une partie des métadonnées EXIF de chaque image en une seule commande (ici date et heure de prise de vue).

$ find -iname "DSC_*" -exec exiv2 -r %Y-%m%d-%Hh%Mm%Ss-chantier mv {} +
$
$ ls -l
total 10004
-rwxr-xr-x 1 sima sima 2976990 2010-06-13 16:07 2010-0613-16h07m08s-chantier.JPG
-rwxr-xr-x 1 sima sima 2538376 2010-06-13 16:07 2010-0613-16h07m27s-chantier.JPG
-rwxr-xr-x 1 sima sima 2231659 2010-06-13 16:07 2010-0613-16h07m51s-chantier.JPG
-rwxr-xr-x 1 sima sima 2472989 2010-06-13 16:07 2010-0613-16h07m57s-chantier.JPG

Que c’est-il passé?
La commande find a recherché les fichiers dont le nom commence par DSC_
Lorsque la réponse est vrai (renvoi 0) exécute la commande exiv2
La commande exiv2 va renommer en prenant l’année (%Y), le mois (%m), le jour (%d), l’heure (%H), les minutes (%M) et les secondes (%S) de prise de vue en y ajoutant les personnalisations les () (hms) de heure, minutes et secondes puis chantier.

En faisant «man exiv2» ou «man find» on peut voir l’étendue des possibilités.

ATTENTION ! cette commande est récursive et si vous avez des sous-répertoires avec des fichiers correspondant à la requête, ils seront également modifiés. Dans ce cas, vous pouvez utiliser la commande exiv2 dans une boucle for, do, done

Il est facile d’en faire un script…

8 réflexions sur « Renommer les photos par lot en utilisant les métadonnées EXIF »

  1. Bonjour Sima, merci pour ce partage.

    Puisque tu mentionnes la question des sous-répertoires qui seraient inclus, je partage le fait de limiter la recherche par [find] avec le paramètre [-maxdepth], précisément avec [-maxdepth 1] afin de limiter la recherche au répertoire donné en paramètre.

    Une autre question est de toujours limiter la portée de find, et puisqu’on ne veut que renommer des fichiers, autant ajouter le filtrage de fichier uniquement avec [-type f].

    Enfin, mes référents en CLI ont toujours conseillé de ne pas utiliser l’option [-exec] de [find], mais de passer par un [pipe] vers la commande [xargs], pour des raisons multiples, comme l’efficacité, les limites de ressources, mais c’est un autre débat.

    J’admets que pour des actions limitées en nombre de fichiers et en actions à faire sur ces fichiers, [find -exec] peut être suffisant, notamment avec l’option [+] à la place de [;] dans [find -exec … +] , et que xargs doit être fiabilisé avec un pipe [find -print0 … | xargs -0 …] pour se prémunir des espaces dans les noms de fichier et chemin.

    J’utilise donc toujours [find|xargs] plutôt que [find -exec] parce que cela fonctionne dans tous les cas et efficacement, et que cela permet de traiter des cas complexes, incluant des [sort,grep, …] et qu’ainsi je ne me pose pas de question, et enfin le pipe en général permet de prototyper plus facilement la commande.

    1. Je suis d’accord sur les points concernant -maxdepth 1 (si l’on ne souhaite pas parcourir les sous-répertoires) et -type f, qui rendent la commande plus explicite et limitent les effets de bord.

      En revanche, je suis plus réservé sur l’idée qu’il faudrait systématiquement préférer find | xargs à find -exec. Avec -exec … +, find regroupe déjà les fichiers par lots, gère correctement les espaces et autres caractères particuliers dans les noms, et respecte les limites de longueur des lignes de commande. Les gains de xargs sont donc faibles dans un cas simple comme celui-ci.

      À mon sens, xargs est surtout intéressant lorsqu’on veut construire un pipeline plus élaboré (avec sort, grep, etc.). Pour simplement appliquer une commande à une liste de fichiers, find -exec … + reste une solution claire, robuste et très lisible.

      Donc pour moi la ligne que je préfère en prenant en compte ce que tu dit est :
      find . -maxdepth 1 -type f -iname "DSC_*" -exec exiv2 -r '%Y-%m%d-%Hh%Mm%Ss-chantier' mv {} +
      Car ici, on ne fait qu’exécuter directement exiv2 sur les fichiers trouvés.
      -exec est donc plus simple.

  2. Je disais à peu près la même chose que toi, je suis d’accord globalement, notamment depuis que _find_ a été amélioré avec le [-exec +].

    Ce que j’ai omis de préciser, c’est que j’ai de vieux réflexes issus des principes comme un des principe Unix, que tu connais : chaque programme doit faire une seule chose, et parfaitement.

    Donc demander à _find_ de chercher puis agir sur le résultat, c’est à l’encontre ce vieux principe.

    … mais bon, mêmes les vieux principes ne sont plus respectés. Regarde _Busybox_ , qui fait tout, et seul! 😲

      1. C’est vrai, d’antant plus que Bash, par exemple, a continuement été amélioré, et que les fonctions que nous utilisons dans ce cas n’existent pas depuis très longtemps, autrement dit, nous pouvons apprendre tous les jours de nouveaux tours d’informagie avec cette bashette magique qui s’améliore tous les jours, plus qu’hier et moins que demain!
        Bravo et merci pour ton site et tes partages.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *