You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The naming/sanitization helpers used when building file and folder names produce malformed names in several cases. All of them come from sanitize_filename() (medusa/helper/common.py#L295) and sanitize_scene_name() (medusa/helpers/init.py#L748), which is used by the %S.N / %E.N tokens via dot() in medusa/tv/episode.py.
Double spaces after removing forbidden characters.sanitize_filename() deletes :"<>|? without collapsing the surrounding whitespace. A show named Example Show : Subtitle becomes Example Show Subtitle (2016) (double space). A name ending in ? can leave a double space before an appended year.
Non-breaking space (U+00A0) is never handled. It is not converted to a separator by sanitize_scene_name(), not removed by sanitize_filename(), and not stripped by the final strip(' .'). Episode titles from TheTVDB can contain NBSP. Result: filenames that end with an invisible non-breaking space, which breaks later path comparisons. Tabs were handled in Strip more invalid filename characters - Fixes #3839 #4351; NBSP remains.
Deleted apostrophes glue words together.sanitize_scene_name() deletes ' and ' outright. Fine for English scene style (Bob's Burgers -> Bobs.Burgers), but for elisions it merges two different words: L'exemple -> Lexemple, C'est un titre -> Cest.un.titre.
Minor, same code path: an empty episode title yields a double dot (Show.S01E01..(2025-01-15)), and %E_N/%S_N leave trailing underscores when a title ends in ?/! because us() converts spaces before punctuation is removed.
To Reproduce
frommedusa.helper.commonimportsanitize_filenamefrommedusa.helpersimportsanitize_scene_namesanitize_filename('Example Show : Subtitle') # 'Example Show Subtitle' (double space)sanitize_filename('example title\xa0?') # 'example title\xa0' (trailing NBSP)sanitize_scene_name("L'exemple de titre") # 'Lexemple.de.titre' (glued words)
Or add a show whose name contains : and let Medusa create the show folder.
Expected behavior
Removing a forbidden character should not leave double separators; e.g. Sonarr collapses repeated separators with ([- ._])(\1)+ and uses a "smart" colon replacement (": " -> " - ", remaining : -> -) in FileNameBuilder.CleanFileName.
NBSP should be treated like a regular space (or stripped at the ends like a space).
Apostrophe removal in the naming context should insert a separator instead of merging words (search/scene matching in name_cache.py / scene_exceptions.py must keep the current behavior, so the change belongs in the dot() naming helper, not in the shared sanitize_scene_name()).
Medusa (please complete the following information):
OS: Windows 10 (also reproducible on any OS; code path is platform-independent)
Branch: develop
Commit: b935f77 (current develop; both functions unchanged)
Python version: 3.13
Database version: n/a (not DB related)
Additional context
Related history: #3839 / #4351 added \t and control characters to sanitize_filename(); NBSP was the remaining invisible character.
Edited to remove personal library show/folder names from the original report.
Describe the bug
The naming/sanitization helpers used when building file and folder names produce malformed names in several cases. All of them come from
sanitize_filename()(medusa/helper/common.py#L295) andsanitize_scene_name()(medusa/helpers/init.py#L748), which is used by the%S.N/%E.Ntokens viadot()inmedusa/tv/episode.py.Double spaces after removing forbidden characters.
sanitize_filename()deletes:"<>|?without collapsing the surrounding whitespace. A show namedExample Show : SubtitlebecomesExample Show Subtitle (2016)(double space). A name ending in?can leave a double space before an appended year.Non-breaking space (U+00A0) is never handled. It is not converted to a separator by
sanitize_scene_name(), not removed bysanitize_filename(), and not stripped by the finalstrip(' .'). Episode titles from TheTVDB can contain NBSP. Result: filenames that end with an invisible non-breaking space, which breaks later path comparisons. Tabs were handled in Strip more invalid filename characters - Fixes #3839 #4351; NBSP remains.Deleted apostrophes glue words together.
sanitize_scene_name()deletes'and'outright. Fine for English scene style (Bob's Burgers->Bobs.Burgers), but for elisions it merges two different words:L'exemple->Lexemple,C'est un titre->Cest.un.titre.Minor, same code path: an empty episode title yields a double dot (
Show.S01E01..(2025-01-15)), and%E_N/%S_Nleave trailing underscores when a title ends in?/!becauseus()converts spaces before punctuation is removed.To Reproduce
Or add a show whose name contains
:and let Medusa create the show folder.Expected behavior
([- ._])(\1)+and uses a "smart" colon replacement (": "->" - ", remaining:->-) in FileNameBuilder.CleanFileName.name_cache.py/scene_exceptions.pymust keep the current behavior, so the change belongs in thedot()naming helper, not in the sharedsanitize_scene_name()).Medusa (please complete the following information):
Additional context
Related history: #3839 / #4351 added
\tand control characters tosanitize_filename(); NBSP was the remaining invisible character.Edited to remove personal library show/folder names from the original report.