id = "tvnamer" name = "tvnamer" homepage = "https://github.com/dbr/tvnamer" description = "A utility to rename files from some.show.s01e03.blah.abc.avi to Some Show - [01x03] - The Episode Name.avi, using data from TheTVDB." executables = ["tvnamer"] [dotfiles] # The README's "Configs" section: "To use your custom configuration, you must # either specify the location using tvnamer --config=/path/to/… or place the # file at ~/.config/tvnamer/tvnamer.json", and the deprecation note beside it — # "WARNING: you have a config at deprecated ~/.tvnamer.json location. Config # must be moved to new location: ~/.config/tvnamer/tvnamer.json". # # Both are written literally rather than as [configHome]: tvnamer/main.py joins # them to the home directory unconditionally — # default_configuration = os.path.expanduser("~/.config/tvnamer/tvnamer.json") # old_default_configuration = os.path.expanduser("~/.tvnamer.json") # — with no reference to $XDG_CONFIG_HOME, so on a machine that has moved its # XDG directories the placeholder would name a file tvnamer never opens. paths = [ "~/.config/tvnamer/tvnamer.json", "~/.tvnamer.json", ] exclude = [] # The config is renaming behaviour — filename_patterns, the output format # strings, output_filename_replacements, language, move_files_destination. # tvnamer's TheTVDB access needs no user key of its own, so nothing here is a # credential. secret = [] # No machine_lines: move_files_destination is a path, but it is a format string # ("/media/tv/{series name}/season {seasonnumber}/") describing a library # layout the user wants everywhere, not a value one machine owns. # tvnamer loads the config at startup and exits when the rename is done. side_effect = false [commands] format = 1 label = "Rename TV episodes" description = "Rename TV episode files using data from TheTVDB. Config-file saving and naming-pattern flags are left out." quality = "ai-draft" parser = { end_of_options = "--", interleave = "permute", long_equals = true, short_attached = true, short_bundles = false } [[commands.source]] id = "readme" kind = "manual" url = "https://github.com/dbr/tvnamer/blob/master/README.md" revision = "2026-10-27" evidence = """ tvnamer will only descend one level into directories unless the `-r` (or `--recursive`) flag is specified. tvnamer --recursive dir1/ The most useful are most likely `--batch`, `--selectfirst` and `--always`: `--selectfirst` will select the first series the search found, but will not automatically rename any episodes. `--always` will ask you select the correct series, then automatically rename all files. `--batch` will not prompt you for anything. It automatically selects the first series search result, and automatically rename all files `--series-id` will allow you to use a specific ID from theTVdb. tvnamer --config=/path/to/mytvnamerconfig.json """ [[commands.field]] id = "paths" label = "Files or directories" type = "path" path = { kind = "any", role = "input", must_exist = true } position = 0 multiple = true min = 1 sources = ["readme"] [[commands.field]] id = "recursive" label = "Recurse into directories" type = "boolean" option = ["--recursive", "-r"] sources = ["readme"] [[commands.field]] id = "selectfirst" label = "Select first search result" type = "boolean" option = ["--selectfirst"] sources = ["readme"] [[commands.field]] id = "always" label = "Always rename" type = "boolean" option = ["--always"] sources = ["readme"] [[commands.field]] id = "batch" label = "Batch (no prompts)" description = "Selects the first result and renames everything. Use carefully." type = "boolean" option = ["--batch"] effect = "overwrite" sources = ["readme"] [[commands.field]] id = "series_id" label = "TheTVDB series ID" type = "integer" option = ["--series-id"] sources = ["readme"] [[commands.field]] id = "config" label = "Config file" type = "path" path = { kind = "file", role = "input", must_exist = true } option = ["--config"] sources = ["readme"] [[commands.task]] id = "interactive" label = "Rename interactively" fields = ["paths", "recursive", "series_id", "config"] required = ["paths"] [[commands.task]] id = "batch" label = "Rename without prompts" set = { batch = [true] } lock = ["batch"] fields = ["paths", "recursive", "series_id", "config"] required = ["paths"] [[commands.group]] id = "basic" label = "Basic" fields = ["paths", "recursive", "series_id"] [[commands.group]] id = "advanced" label = "Advanced" fields = ["selectfirst", "always", "batch", "config"]