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.
La commande rename1) 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
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 expressions de rationnelles de Perl.
source : 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 ! 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