diff --git a/unshackle/core/config.py b/unshackle/core/config.py index 47407014..cfc651ae 100644 --- a/unshackle/core/config.py +++ b/unshackle/core/config.py @@ -213,7 +213,11 @@ class Config: warnings.warn(f"Unknown template variable '{var}' in {template_type} template") test_template = re.sub(r"\{[^}]+\}", "TEST", template_str) - if re.search(unsafe_chars, test_template): + if template_type.startswith("folder"): + unsafe_segment = any(re.search(unsafe_chars, seg) for seg in re.split(r"[\\/]", test_template)) + else: + unsafe_segment = bool(re.search(unsafe_chars, test_template)) + if unsafe_segment: warnings.warn(f"Template '{template_type}' may contain filesystem-unsafe characters") if not template_str.strip(): diff --git a/unshackle/core/titles/episode.py b/unshackle/core/titles/episode.py index 13196afb..d76bfd31 100644 --- a/unshackle/core/titles/episode.py +++ b/unshackle/core/titles/episode.py @@ -102,15 +102,12 @@ class Episode(Title): if folder: template = config.get_folder_template("series") if template: - formatter = TemplateFormatter(template) context = self._build_template_context(media_info, show_service) context["season"] = f"S{self.season:02}" - - folder_name = formatter.format(context) - - separators = re.sub(r"\{[^}]*\}", "", template) - spacer = "." if "." in separators and " " not in separators else " " - return "/".join(sanitize_filename(p, spacer) for p in folder_name.split("/") if p) + segments = [ + TemplateFormatter(seg).format(context) for seg in re.split(r"[\\/]", template) if seg.strip() + ] + return "/".join(s for s in segments if s) series_template = config.output_template.get("series") if series_template: diff --git a/unshackle/core/titles/movie.py b/unshackle/core/titles/movie.py index a1638367..399e9d0c 100644 --- a/unshackle/core/titles/movie.py +++ b/unshackle/core/titles/movie.py @@ -62,13 +62,11 @@ class Movie(Title): if folder: template = config.get_folder_template("movies") if template: - formatter = TemplateFormatter(template) context = self._build_template_context(media_info, show_service) - folder_name = formatter.format(context) - - separators = re.sub(r"\{[^}]*\}", "", template) - spacer = "." if "." in separators and " " not in separators else " " - return "/".join(sanitize_filename(p, spacer) for p in folder_name.split("/") if p) + segments = [ + TemplateFormatter(seg).format(context) for seg in re.split(r"[\\/]", template) if seg.strip() + ] + return "/".join(s for s in segments if s) name = f"{self.name}" if self.year: name += f" ({self.year})" diff --git a/unshackle/core/titles/music.py b/unshackle/core/titles/music.py index 70c3abbf..c3a77882 100644 --- a/unshackle/core/titles/music.py +++ b/unshackle/core/titles/music.py @@ -170,13 +170,11 @@ class Song(Title): # legacy "songs" folder template, then to "{artist} - {album} ({year})". template = config.get_folder_template("albums") or config.get_folder_template("songs") if template: - formatter = TemplateFormatter(template) context = self._build_template_context(media_info, show_service) - folder_name = formatter.format(context) - - separators = re.sub(r"\{[^}]*\}", "", template) - spacer = "." if "." in separators and " " not in separators else " " - return sanitize_filename(folder_name, spacer) + segments = [ + TemplateFormatter(seg).format(context) for seg in re.split(r"[\\/]", template) if seg.strip() + ] + return "/".join(s for s in segments if s) name = f"{self.artist} - {self.album}" if self.year: name += f" ({self.year})" diff --git a/unshackle/core/titles/song.py b/unshackle/core/titles/song.py index 750168e4..298f1792 100644 --- a/unshackle/core/titles/song.py +++ b/unshackle/core/titles/song.py @@ -97,13 +97,11 @@ class Song(Title): if folder: template = config.get_folder_template("songs") if template: - formatter = TemplateFormatter(template) context = self._build_template_context(media_info, show_service) - folder_name = formatter.format(context) - - separators = re.sub(r"\{[^}]*\}", "", template) - spacer = "." if "." in separators and " " not in separators else " " - return "/".join(sanitize_filename(p, spacer) for p in folder_name.split("/") if p) + segments = [ + TemplateFormatter(seg).format(context) for seg in re.split(r"[\\/]", template) if seg.strip() + ] + return "/".join(s for s in segments if s) name = f"{self.artist} - {self.album}" if self.year: name += f" ({self.year})"