]> gitweb.pimeys.fr Git - scripts-20-100.git/commitdiff
Script pour batch-rename des épisodes de séries selon mon format de noms préféré
authorVincent Le Gallic <legallic@crans.org>
Thu, 11 Jun 2015 02:16:37 +0000 (04:16 +0200)
committerVincent Le Gallic <legallic@crans.org>
Sat, 25 Jul 2015 16:06:19 +0000 (18:06 +0200)
rename_series.py [new file with mode: 0755]

diff --git a/rename_series.py b/rename_series.py
new file mode 100755 (executable)
index 0000000..dd4e0fe
--- /dev/null
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+""" Pour renommer en masse les épisodes d'une série à partir d'un fichier
+    de titres. """
+
+import re
+import os
+import os.path
+import argparse
+import pprint
+
+FORMAT = "%%(series_name)s - [%%(season)0%(logmaxseason)sdx%%(episode)0%(logmaxepisode)sd] - %%(title)s.%%(extension)s"
+
+SEASONEPISODE_REGEXP = ur"^(?P<series_name>([A-Za-z0-9_-]+(\.| ))+)(S|\[)(?P<season>\d+)(E|x)(?P<episode>\d+).*\.(?P<extension>[a-z0-9]*)$"
+sep_re = re.compile(SEASONEPISODE_REGEXP)
+
+def get_titles(filename, debug=False, oneintwo=False):
+    """Récupère les titres des épisodes dans le fichier"""
+    text = open(filename).read()
+    if oneintwo:
+        # On enlève une ligne sur deux
+        text = re.sub("(.*\n).*\n", r'\1', text)
+    titles = re.findall('"(.*)"', text)
+    if debug:
+        print "Titres :"
+        pprint.pprint(titles)
+    return titles
+
+def proper_name(name):
+   """Proprifie le nom de la série."""
+   return name.replace(".", " ").strip()
+
+def get_files(titlesfilename, debug=False):
+    """Récupère les fichiers locaux, en enlevant le fichier de titres.
+       Les analyse à coup de regexp et les renvoie dans un dico. Clé = n° de l'épisode."""
+    files = os.listdir(".")
+    if titlesfilename in files:
+        files.remove(titlesfilename)
+    dir = {}
+    for filename in files:
+        o = sep_re.match(filename)
+        if o:
+            d = o.groupdict()
+            d["episode"] = int(d["episode"])
+            d["season"] = int(d["season"])
+            if dir.has_key(d["episode"]):
+                raise ValueError("Épisode %s trouvé deux fois." % d["episode"])
+
+            dir[d["episode"]] = (filename, d)
+        else:
+            raise ValueError("Unparsable file : %s" % filename)
+    if debug:
+        print "Fichiers :"
+        pprint.pprint(dir)
+    return dir
+
+def process(dir, titles, maxseason, seriesname, args):
+    """Prépare tous les renommages.
+       Renvoie une map before -> after."""
+    series_names = set([proper_name(d["series_name"]) for (_, d) in dir.values()])
+    if seriesname:
+        series_name = seriesname
+    elif len(series_names) > 1:
+        print "Plusieurs titres trouvés :"
+        print list(series_names)
+        series_name = raw_input("Spécifier titre : ")
+    else:
+        series_name = list(series_names)[0]
+    l = range(1, len(dir) + 1)
+    eps = dir.keys()
+    eps.sort()
+    if eps != l:
+        raise ValueError("Il manque des épisodes : %s" % eps)
+    if len(titles) != len(eps):
+        print "Pas autant de titres que d'épisodes : on retente en lisant une ligne sur deux."
+        titles = get_titles(args.titles, oneintwo=True)
+        if len(titles) != len(eps):
+            raise ValueError("Pas autant de titres que d'épisodes !")
+    formatdir = {
+        "logmaxseason" : len(str(maxseason)),
+        "logmaxepisode" : len(str(max(eps))),
+        "series_name" : series_name
+    }
+    map = []
+    for k in eps:
+        (before, d) = dir[k]
+        d.update(formatdir)
+        d["title"] = titles[k-1]
+        newname = FORMAT % d
+        newname = newname % d
+        map.append((before, newname))
+    return map
+def confirm(map):
+    """Affiche ce qui va être fait et demande confirmation."""
+    size = max([len(b) for (b, a) in map])
+    for (b, a) in map:
+        print "%s%s →  %s" % (b, " " * (size - len(b)), a)
+    ans = raw_input("Renommer ?")
+    return ans.lower() in ["y", "o", "yes", "oui"]
+
+
+def do(map):
+    """Fait le renommage."""
+    for (before, after) in map:
+        os.rename(before, after)
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description="Renommage en batch d'épisodes de série.")
+    parser.add_argument('-v', '--verbose', help="Afficher du debug", action="store_true")
+    parser.add_argument('-q', '--quiet', help="Ne pas afficher les warnings", action="store_true")
+    parser.add_argument('-t', '--titles', help="Fichier contenant les titres des épisodes", action="store", type=str, default="titles")
+    parser.add_argument('-m', '--maxseason', help="Nombre total de saisons (pour le nombre de 0)", action="store", type=str, default=1)
+    parser.add_argument('-s', '--seriesname', help="Override le nom de la série", action="store", type=str)
+    
+    args = parser.parse_args()
+    
+    titles = get_titles(args.titles, args.verbose)
+    files = get_files(args.titles, args.verbose)
+    map = process(files, titles, args.maxseason, args.seriesname, args)
+    if confirm(map):
+        do(map)