83 votes

Renommer des fichiers à l'aide d'expressions régulières sous Linux

J'ai un ensemble de fichiers nommés comme suit :

Friends - 6x03 - Tow Ross' Denial.srt
Friends - 6x20 - Tow Mac and C.H.E.E.S.E..srt
Friends - 6x05 - Tow Joey's Porshe.srt

et je veux les renommer comme suit

S06E03.srt
S06E20.srt
S06E05.srt

que dois-je faire pour que le travail soit fait dans le terminal linux ? J'ai installé rename mais j'obtiens des erreurs en utilisant ce qui suit :

rename -n 's/(\w+) - (\d{1})x(\d{2})*$/S0$2E$3\.srt/' *.srt

95voto

Thor Points 13562

Vous avez oublié un point devant l'astérisque :

rename -n 's/(\w+) - (\d{1})x(\d{2}).*$/S0$2E$3\.srt/' *.srt

Sur OpenSUSE, RedHat, Gentoo, vous devez utiliser la version Perl de rename . Cette réponse montre comment l'obtenir. Sur Arch, le paquetage s'appelle perl-rename .

35voto

Jonathan Komar Points 511

Un petit truc vraiment sympa. find + perl + xargs + mv

xargs -n2 permet d'imprimer deux arguments par ligne. Combiné à la fonction print $_ (pour imprimer le $STDIN en premier), il constitue un puissant outil de renommage.

find . -type f | perl -pe 'print $_; s/input/output/' | xargs -d "\n" -n2 mv

Résultats de perl -pe 'print $_; s/OldName/NewName/' | xargs -n2 finissent par l'être :

OldName.ext    NewName.ext
OldName.ext    NewName.ext
OldName.ext    NewName.ext
OldName.ext    NewName.ext

Je ne disposais pas de la fonction rename disponible sur mon système.


Comment cela fonctionne-t-il ?

  1. find . -type f produit des chemins d'accès aux fichiers (ou des noms de fichiers... vous contrôlez ce qui est traité par les expressions rationnelles ici !)
  2. -p imprime les chemins d'accès aux fichiers qui ont été traités par les expressions rationnelles, -e exécute un script en ligne
  3. print $_ imprime d'abord le nom du fichier original (indépendamment de -p )
  4. -d "\n" coupe l'entrée par une nouvelle ligne, au lieu du caractère espace par défaut
  5. -n2 imprime deux éléments par ligne
  6. mv récupère l'entrée de la ligne précédente

Mon approche préférée, bien que plus avancée.

Supposons que je veuille renommer tous les fichiers ".txt" en fichiers ".md" :

find . -type f -printf '%P\0' | perl -0 -l0 -pe 'print $_; s/(.*)\.txt/$1\.md/' | xargs -0 -n 2 mv

La magie réside dans le fait que chaque processus du pipeline prend en charge l'octet nul (0x00) qui est utilisé comme délimiteur par opposition aux espaces ou aux nouvelles lignes. La méthode susmentionnée utilise les nouvelles lignes comme séparateurs. Non pas que j'aie essayé de supporter facilement find . sans utiliser de sous-processus. Soyez prudent ici (vous pourriez vouloir vérifier votre sortie de find avant de le soumettre à une expression régulière ou, pire encore, à une commande destructrice telle que mv ).

Fonctionnement (abrégé pour n'inclure que les changements ci-dessus)

  1. En find : -printf '%P\0' n'imprime que le nom des fichiers sans chemin d'accès suivi d'un octet nul. Adaptez-vous à votre cas d'utilisation, qu'il s'agisse de noms de fichiers ou de chemins entiers.
  2. En perl y xargs : -0 le délimiteur stdin est l'octet nul (au lieu de l'espace)
  3. En perl : -l0 le délimiteur de stdout est l'octet nul (en octal 000)

12voto

Creak Points 50

Editer : a trouvé une meilleure façon de lister les fichiers sans utiliser la fonction IFS y ls tout en étant sh conforme.

Je ferais un shell script pour cela :

#!/bin/sh
for file in *.srt; do
  if [ -e "$file" ]; then
    newname=`echo "$file" | sed 's/^.*\([0-9]\+\)x\([0-9]\+\).*$/S0\1E\2.srt/'`
    mv "$file" "$newname"
  fi
done

Précédent script :

#!/bin/sh
IFS='
'
for file in `ls -1 *.srt`; do
  newname=`echo "$file" | sed 's/^.*\([0-9]\+\)x\([0-9]\+\).*$/S0\1E\2.srt/'`
  mv "$file" "$newname"
done

11voto

xoxox Points 472

Utilisation mmv (mouvement de masse ?)

C'est simple mais utile : Le * Le caractère générique correspond à n'importe quelle chaîne de caractères (sans barre oblique) et ? correspond à n'importe quel caractère de la chaîne à rechercher. Utiliser #X dans la chaîne de remplacement pour faire référence à la Xème correspondance de caractères génériques.

Dans votre cas :

mmv 'Friends - 6x?? - Tow *.srt' 'S06E#1#2.srt'

Ici #1#2 représentent les deux chiffres qui sont capturés par ?? (match #1 et #2).
Le remplacement suivant est donc effectué :

Friends - 6x?? - Tow *           .srt    matches
Friends - 6x03 - Tow Ross' Denial.srt    which is replaced by

        S06E03.srt

mmv offre également un service d'appariement par [ y ] y ; .

Vous pouvez non seulement masser renommer mais aussi la masse déplacer, copier, ajouter y lien des dossiers.

Voir le page de manuel pour en savoir plus !

Personnellement, je l'utilise pour remplir les numéros de façon à ce que les fichiers numérotés apparaissent dans l'ordre souhaité lorsqu'ils sont triés lexicographiquement (par exemple, 1 apparaît avant 10) : file_?.ext file_0#1.ext

10voto

Toutes les distros ne fournissent pas un rename qui prend en charge les expressions rationnelles telles qu'elles sont utilisées dans les exemples ci-dessus - RedHat, Gentoo et leurs dérivés, entre autres.

Les alternatives à essayer d'utiliser sont perl-rename y mmv .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X