Utiliser sed et les regex pour déplacer une partie de nom de fichier

Un petit mémo (pour moi ou d’autres qui seraient intéressés qui peut d’ailleurs servir de mini tuto à l’utilisation de sed. Je ne rentrerai pas dans les détails sur ce qu’est sed, Internet fourmille d’informations et vous n’avez qu’à demander à un moteur de recherche.

Dans mon cas, je dispose de fichiers de la forme suivante :

image000010_bureauc-20140604_Kinect_gw_CB3D_adpt_L1P1.bmp

Chaque élément du nom de fichier est important et apporte une information sur la façon dont il a été généré. Dans un seul et unique dossier de résultats, je dispose de fichiers nommés comme précédemment, mais un seul élément change : la partie rouge. Cette partie peut avoir plus de 10 valeurs différentes.

Comme les images se suivent, le dossier liste les fichiers dans l’ordre numérique. J’ai donc une succession de plus de 10 d’images numérotées « 000010 », autant que j’ai de parties rouges différentes. La solution est donc de déplacer cette partie rouge au début du nom de fichier.

Or, pas facile de faire ça à la main sur des centaines d’images. On va scripter ça en bash avec des expressions régulières. Notez qu’on pourrait utiliser la commande rename mais je ne connais pas très bien sa syntaxe.

On va donc écrire une expression régulière qui va matcher nos noms de fichiers actuels, la découper en 3 morceaux et redisposer les morceaux dans l’ordre qu’on souhaite.

's/(image[0-9]{6}_bureauc-20140604_Kinect_)([a-zA-Z0-9]{1,8})_(CB[0-9]D_adpt_L[0-9]P[0-9].bmp)/\2_\1\3/'

Les parenthèses ( ) définissent des groupes numérotés dans l’ordre, que l’on réutilise en 2ème partie de la regex pour les redisposer dans l’ordre souhaité.

La commande finale pour obtenir le nouveau nom de fichier est donc :

newfilename=$(echo "$filename" | sed -r 's/(image[0-9]{6}_bureauc-20140604_Kinect_)([a-zA-Z0-9]{1,8})_(CB[0-9]D_adpt_L[0-9]P[0-9].bmp)/\2_\1\3/')

Note : il est possible de considérer une liste de valeurs acceptables pour chaque élément. Par exemple l’élément représenté par « Kinect » ici peut aussi être « BB2 ». On teste le matching de plusieurs valeurs avec une parenthèse comme ceci

$(echo "$filename" | sed -r 's/(image[0-9]{6}_bureauc-20140604_(BB2|Kinect)_)([a-zA-Z0-9]{1,8})_(CB[0-9]D_adpt_L[0-9]P[0-9].bmp)/\3_\1\4/')

Notez que ceci ajoute un nouveau groupe numéroté 2. Comme il est imbriqué dans le groupe 1, on ne va pas s’en servir dans la seconde partie de la regex. Par contre, ça décale les numéros des groupes suivants, aussi le dernier groupe devient le numéro 4.