123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #!/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)
|