|
@@ -0,0 +1,206 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+# coding: utf-8
|
|
|
+"""
|
|
|
+Created on Wed Jul 13 10:52:12 2024
|
|
|
+
|
|
|
+@author: ajco7475
|
|
|
+"""
|
|
|
+import sys
|
|
|
+import os
|
|
|
+import re
|
|
|
+import getopt
|
|
|
+from colorama import init, Fore, Style
|
|
|
+import random
|
|
|
+import logging
|
|
|
+import platform
|
|
|
+
|
|
|
+logger = logging.getLogger("RENAMER")
|
|
|
+logging.basicConfig()
|
|
|
+
|
|
|
+init(autoreset=True)
|
|
|
+
|
|
|
+
|
|
|
+def color_text(text, color):
|
|
|
+ return f"{color}{text}{Fore.RESET}"
|
|
|
+
|
|
|
+
|
|
|
+# =============================================================================
|
|
|
+# usage
|
|
|
+#
|
|
|
+# - afficher le message d'aide
|
|
|
+# =============================================================================
|
|
|
+def set_log_level(log_level):
|
|
|
+ if log_level == "CRITICAL":
|
|
|
+ logger.setLevel(logging.CRITICAL)
|
|
|
+ elif log_level == "ERROR":
|
|
|
+ logger.setLevel(logging.ERROR)
|
|
|
+ elif log_level == "WARNING":
|
|
|
+ logger.setLevel(logging.WARNING)
|
|
|
+ elif log_level == "INFO":
|
|
|
+ logger.setLevel(logging.INFO)
|
|
|
+ else:
|
|
|
+ if log_level is None:
|
|
|
+ print("INFO: log level is set to 'DEBUG' by default")
|
|
|
+ elif log_level != "DEBUG":
|
|
|
+ print(
|
|
|
+ "INFO: specified log_level value ({}) is incorrect, use CRITICAL, ERROR, WARNING, INFO or DEBUG. log "
|
|
|
+ "level is set to 'DEBUG' by default".format(log_level))
|
|
|
+ logger.setLevel(logging.DEBUG)
|
|
|
+
|
|
|
+
|
|
|
+# =============================================================================
|
|
|
+# clean_file_name
|
|
|
+#
|
|
|
+# - afficher le message d'aide
|
|
|
+# =============================================================================
|
|
|
+def clean_file_name(old_filename):
|
|
|
+ new_filename = None
|
|
|
+ parts = old_filename.rsplit('.', 1) # Divise à partir du dernier point
|
|
|
+ if len(parts) == 2:
|
|
|
+ # Remplace tous les points dans la première partie
|
|
|
+ parts[0] = re.sub(r'\.', ' ', parts[0])
|
|
|
+ new_filename = parts[0] + '.' + parts[1]
|
|
|
+ else:
|
|
|
+ # S'il n'y a pas de point, ou juste un à la fin, retourne la chaîne inchangée
|
|
|
+ new_filename = old_filename
|
|
|
+ # remplacement de DVDRip et marques suivantes
|
|
|
+ new_filename = re.sub(r'(.*)\s+DVDRip\b.*\.(\w+)$', r'\1.\2', new_filename)
|
|
|
+ # nettoyage de 1080p ... et 720p ...
|
|
|
+ new_filename = re.sub(r'(.*)(\d\d\d+p).*\.(\w+)$', r'\1\2.\3', new_filename)
|
|
|
+ # ntettoyage de x264 ... x265 ...
|
|
|
+ new_filename = re.sub(r'(.*)(\s+x26\d).*\.(\w+)$', r'\1.\3', new_filename)
|
|
|
+ # ntettoyage de ... - ...
|
|
|
+ new_filename = re.sub(r'\s+-\s+', ' ', new_filename)
|
|
|
+ # mise en parenthéses de l'année
|
|
|
+ new_filename = re.sub(r'\b(\d\d\d\d)\b', r'(\1)', new_filename)
|
|
|
+ # suppression des blancs au debut
|
|
|
+ new_filename = re.sub(r'^\s+', '', new_filename)
|
|
|
+ # suppression des blancs à la fin
|
|
|
+ new_filename = re.sub(r'\s+$', '', new_filename)
|
|
|
+ # remplacement d'un planc par un seul underscore
|
|
|
+ new_filename = re.sub(r'\s+', '_', new_filename)
|
|
|
+ # remplacement de plusieures parentheses ouvrantes
|
|
|
+ new_filename = re.sub(r'\(\(+', '(', new_filename)
|
|
|
+ # remplacement de plusieures parentheses fermantes
|
|
|
+ new_filename = re.sub(r'\)\)+', ')', new_filename)
|
|
|
+ logger.debug(f"old_filename=<{old_filename}> new_filename=<{new_filename}>")
|
|
|
+ return new_filename
|
|
|
+
|
|
|
+
|
|
|
+# =============================================================================
|
|
|
+# rename_files_in_directory
|
|
|
+#
|
|
|
+# - afficher le message d'aide
|
|
|
+# =============================================================================
|
|
|
+def rename_files_in_directory(
|
|
|
+ directory_path,
|
|
|
+ pattern=None,
|
|
|
+ new_prefix=None,
|
|
|
+ no_underscore=False,
|
|
|
+ test=False):
|
|
|
+ """
|
|
|
+ Renomme les fichiers dans le répertoire spécifié selon un certain motif.
|
|
|
+
|
|
|
+ :param directory_path: Chemin du répertoire à parcourir.
|
|
|
+ :param pattern: Motif regex pour correspondre les noms de fichiers actuels.
|
|
|
+ :param new_pattern: Motif pour renommer les fichiers.
|
|
|
+ """
|
|
|
+ # Vérifier si le répertoire existe
|
|
|
+ if not os.path.isdir(directory_path):
|
|
|
+ print(f"Le répertoire {directory_path} n'existe pas.")
|
|
|
+ return
|
|
|
+
|
|
|
+ if pattern is None:
|
|
|
+ pattern = r".*"
|
|
|
+ logger.debug(f"pattern=<{pattern}> new_prefix=<{new_prefix}> no_underscore=<{no_underscore}>")
|
|
|
+
|
|
|
+ # Parcourir tous les fichiers dans le répertoire
|
|
|
+ for filename in os.listdir(directory_path):
|
|
|
+ # Chemin complet du fichier
|
|
|
+ file_path = os.path.join(directory_path, filename)
|
|
|
+
|
|
|
+ # Vérifier si c'est un fichier
|
|
|
+ if os.path.isfile(file_path):
|
|
|
+ logger.debug(f"file_path=<{file_path}>")
|
|
|
+ # Utiliser l'expression régulière pour correspondre le nom de fichier
|
|
|
+ match = re.match(pattern, filename)
|
|
|
+ if match:
|
|
|
+ # Construire le nouveau nom de fichier
|
|
|
+ new_filename = clean_file_name(filename)
|
|
|
+ if new_prefix is not None:
|
|
|
+ pattern = re.compile(r'(?i)^(.*?)(S(\d+)E(\d+))')
|
|
|
+ match = re.search(pattern, new_filename)
|
|
|
+ logger.debug(f"<<{match.group()}>> {match.lastindex} ---> {new_prefix}")
|
|
|
+ saison = "{:02}".format(int(match.group(3)))
|
|
|
+ episode = "{:02}".format(int(match.group(4)))
|
|
|
+ logger.debug(
|
|
|
+ "saison : " + color_text(saison, Fore.BLUE) + " episode : " + color_text(episode, Fore.RED))
|
|
|
+ new_filename = pattern.sub(f'{new_prefix}_S{saison}E{episode}', new_filename)
|
|
|
+ # si demandé enlever les underscores
|
|
|
+ if no_underscore:
|
|
|
+ new_filename = new_filename.replace('_',' ')
|
|
|
+ # Renommer le fichier
|
|
|
+ new_file_path = os.path.join(directory_path, new_filename)
|
|
|
+ if not test:
|
|
|
+ os.rename(file_path, new_file_path)
|
|
|
+ print("<<< " + color_text(file_path, Fore.BLUE) + "\n>>> " + color_text(new_file_path, Fore.RED))
|
|
|
+
|
|
|
+
|
|
|
+# =============================================================================
|
|
|
+# usage
|
|
|
+#
|
|
|
+# - afficher le message d'aide
|
|
|
+# =============================================================================
|
|
|
+def usage():
|
|
|
+ script_name = os.path.basename(__file__)
|
|
|
+ print(f"{script_name} : () facultative item, <> : mandatory item\n"
|
|
|
+ " (--prefix=<prefix string>) : prefixe a placer devant SxxExx\n"
|
|
|
+ " (--rd=<prefix string>) : repertoire à parcourir\n"
|
|
|
+ " (--nu) : supprimer le 'underscore' du nom final du fichier cible\n"
|
|
|
+ " (--test) : afficher les transformations sans effectuer le rennomage\n"
|
|
|
+ " (--ll=<log level:CRITICAL|ERROR|WARNING|INFO|DEBUG>)\n"
|
|
|
+ " (-h) : this help\n")
|
|
|
+
|
|
|
+
|
|
|
+# =============================================================================
|
|
|
+# MAIN
|
|
|
+# =============================================================================
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ # nouveau prefix
|
|
|
+ prefix = None
|
|
|
+ # niveau de logs par défaut
|
|
|
+ ll = 'INFO'
|
|
|
+ # repertoire à addresser
|
|
|
+ ren_dir = None
|
|
|
+ # supprimer le 'underscore' du nom final du fichier cible
|
|
|
+ no_underscore = False
|
|
|
+ # afficher les transformations sans effectuer le rennomage
|
|
|
+ do_test = False
|
|
|
+ try:
|
|
|
+ opts, args = getopt.getopt(sys.argv[1:], "h",
|
|
|
+ ["prefix=", "rd=", "nu", "test", "ll="])
|
|
|
+ except getopt.GetoptError as err:
|
|
|
+ logger.error(err)
|
|
|
+ usage()
|
|
|
+ sys.exit(2)
|
|
|
+ for opt, arg in opts:
|
|
|
+ if opt == '-h':
|
|
|
+ usage()
|
|
|
+ sys.exit()
|
|
|
+ elif opt in "--prefix":
|
|
|
+ prefix = arg
|
|
|
+ elif opt in "--rd":
|
|
|
+ ren_dir = arg
|
|
|
+ elif opt in "--nu":
|
|
|
+ no_underscore = True
|
|
|
+ elif opt in "--test":
|
|
|
+ do_test = True
|
|
|
+ elif opt in "--ll":
|
|
|
+ if arg in ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]:
|
|
|
+ ll = arg
|
|
|
+ # log level
|
|
|
+ set_log_level(ll)
|
|
|
+ if ren_dir is None:
|
|
|
+ ren_dir = os.getcwd()
|
|
|
+ rename_files_in_directory(ren_dir, new_prefix=prefix, no_underscore=no_underscore,test=do_test)
|