====== Renommer des fichiers en masse ======
===== Cas d'utilisation =====
Je souhaite que les nouveaux noms de fichiers exploitent une partie de l'information contenue dans les anciens noms de manière différente selon les situations. Deux situations typiques sont l'uniformisation de noms de fichiers et la suppression de méta-données inscrites dans les noms de fichiers.
Les capacités de substitution du shell étant insuffisantes, les solutions présentées dans cette fiche s'appuient sur les expressions rationnelles.
Le pouvoir expressif et la syntaxe des expressions rationnelles varient d'une application/commande à l'autre.
Les commandes présentées ici étant susceptibles d'avoir des effets massifs et irréversibles, il est vivement conseillé de travailler sur des copies ou de tester intensivement les expressions utilisées avant de les utiliser en situation réelle.
===== rename =====
La commande //rename//((Si elle n'est pas installée sur votre système debian-like, //apt install rename// débloquera la situation.)) est pratique pour renommer des ensembles de fichiers. Sa syntaxe relativement simple permet de se focaliser sur les expressions rationnelles à rédiger. De plus, elle propose un mode //test// qui permet d'éviter de faire des grosses bêtises LOL
Voici un exemple typique où je souhaite supprimer les méta-données présentes en début de nom de fichier, encadrées par les crochets et suivies d'un espace (ex. : "[mes méta données super_préceuses] mon-fichier.ext").
rename -n -d 's/^\[.*\] (.*)/$1/' *.ext
Dans cet exemple simple, je limite le traitement aux fichiers d'extension "ext" présents dans le répertoire courant. L'option "-n" est la fameuse option de test. Elle précise qu'il ne faut pas effectuer le renommage mais d'afficher les changements qui seraient réalisés.
Pour en savoir plus sur //rename// :
rename -h
//rename// s'appuie sur les [[https://perldoc.perl.org/perlre|expressions de rationnelles de Perl]].
===== find + perl + mv =====
source : [[https://stackoverflow.com/questions/11809666/rename-files-using-regular-expression-in-linux|Rename files using regular expression in linux]]
Cette solution offre une alternative si commande "rename" n'est pas disponible dans votre distribution. Elle ouvre également aux capacités de sélection de la commande //find//. Elle s'appuie explicitement sur les expression rationnelles de //Perl//. On constate qu'elle combine et enchaîne 4 commandes :
find . -type f | perl -pe 'print $_; s/input/output/' | xargs -d "\n" -n2 mv
où "input" et "output" définissent la sélection et la transformation des motifs.
Si l'on veut afficher les modifications de noms de fichiers qui seraient appliquées sans les effectuer, il suffit de tronquer le dernier enchaînement :
find . -type f | perl -pe 'print $_; s/input/output/'
À titre d'exemple, voici une ligne de commandes semblable à celle présentée pour //rename//.
find . -maxdepth 1 -type f -name "*.ext" | perl -pe 'print $_; s/^(\.\/)(.*\/)*\[.*\] (.*)$/$1$2$3/' | xargs -d "\n" -n2 mv -n
Très verbeux pour le même résultat ! LOL On notera cependant que l'option //maxdepth// permet de régler aussi finement qu'on le souhaite la profondeur à laquelle on veut appliquer le renommage, dans l'arborescence courante (récursion). C'est pourquoi l'expression régulière a été "renforcée" afin de pouvoir s'appliquer à n'importe quelle profondeur, sans risque d'effet de bord.
La décomposition des actions donne accès aux possibilités de paramétrage de chaque commande. Je l'ai illustré avec la commande //mv//. Ici, l'option "-n" permet d'éviter que notre opération de renommage ne vienne écraser un fichier existant. Une sage précaution lorsqu'on lance une telle opération sur toute une arborescence.
Enfin, moyennant quelques adaptations, une chaîne de commandes similaire pourrait créer une arborescence de liens symboliques portant les nouveaux noms, dans un répertoire parallèle, sans toucher aux fichiers originaux… Dans l'exemple suivant, on se contente de créer des liens symboliques, dans les mêmes répertoires que les fichiers originaux. Il a suffit de remplacer "mv -n" par "ln -s" ;-)
find . -maxdepth 1 -type f -name "*.ext" | perl -pe 'print $_; s/^(\.\/)(.*\/)*\[.*\] (.*)$/$1$2$3/' | xargs -d "\n" -n2 ln -s