Skip to content

psclkoch/medianame

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

medianame

Tests License: MIT Python 3.9+

CLI tool to create Plex- or Jellyfin-compatible folder structures for movies and TV shows.

Search by title, confirm, done β€” medianame creates properly named folders with the correct metadata tags so your media server can match them automatically.

What it does

$ medianame inception
  πŸ” Inception (2010) β€” Movie β€” starring Leonardo DiCaprio, Joseph Gordon-Levitt
     Correct? (Enter/n):
  βœ… tt1375666 confirmed.
βœ… Created: Inception (2010) {imdb-tt1375666}

$ medianame breaking bad
  πŸ” Breaking Bad (2008) β€” TV Show β€” starring Bryan Cranston, Aaron Paul
     Correct? (Enter/n):
  πŸ“Ί Seasons to create (TMDB: 5, Enter = accept):
  βœ… tmdb-1396 confirmed.
βœ… Created: Breaking Bad (2008) {tmdb-1396}
   βœ… Season 01
   βœ… Season 02
   βœ… Season 03
   βœ… Season 04
   βœ… Season 05

Naming conventions

medianame supports two naming presets:

Plex β€” naming docs:

  • Movies: Title (Year) {imdb-ttXXXXXXX}
  • TV shows: Title (Year) {tmdb-XXXXX} with Season 01, Season 02, … subfolders

Jellyfin β€” naming docs:

  • Movies: Title (Year) [imdbid-ttXXXXXXX] or [tmdbid-XXXXX]
  • TV shows: Title (Year) [tmdbid-XXXXX] or [imdbid-ttXXXXXXX]

Unlike Plex, Jellyfin lets you choose either IMDb or TMDB IDs for both media types β€” configurable during setup.

Installation

Requirements: Python 3.9+ and pipx (recommended) or pip.

# Clone the repository
git clone https://github.com/psclkoch/medianame.git
cd medianame

# Install with pipx (recommended)
pipx install -e .

# Or with pip
pip install -e .

On first run, medianame will walk you through the setup:

$ medianame
Not configured yet. Starting setup...

==================================================
  🎬 medianame β€” First-time setup
==================================================

ℹ️ Press Enter at any prompt with a default in [brackets] to accept it.

1) TMDB Read Access Token (for title search, movies, TV shows, cast)
2) Movie working folder (library root, or a staging area β€” see step 11)
3) TV show working folder (library root, or a staging area β€” see step 12)
4) Media server (plex / jellyfin)
5) Movie ID source        (Jellyfin only β€” imdb / tmdb)
6) TV show ID source      (Jellyfin only β€” imdb / tmdb)
7) Default operation for `scan` (move / copy)
8) Minimum video size for `scan` (in MB, default 500)
9) Extra scan ignores (comma-separated; defaults cover #recycle, @eaDir, …)
10) Default max age (days) for `scan` (0 = no limit)
11) Movie library folder β€” optional Plex/Jellyfin target for `publish`
12) TV show library folder β€” optional Plex/Jellyfin target for `publish`

βœ… Configuration saved: ~/.config/medianame/config.json

Your configuration is stored in ~/.config/medianame/config.json. Run medianame setup at any time to change it β€” existing values are shown in brackets and kept by pressing Enter (nothing needs to be re-typed).

Usage

medianame                        # Interactive mode β€” enter titles one by one
medianame <title>                # Direct search (e.g. medianame the matrix)
medianame -n <title>             # Dry run β€” show what would be created
medianame -o /path <title>       # Override target path for this run
medianame -f movies.txt          # Batch mode β€” process IMDb URLs from a file
medianame --preset jellyfin ...  # Override naming preset for this run
medianame scan [<path>]          # Scan a folder and move raw media into named folders
medianame scan --copy <path>     # Same, but copy instead of move
medianame scan --max-age-days 7  # Only scan entries modified in the last 7 days
medianame scan --no-publish      # Scan without the auto-publish step this run
medianame publish [<path>]       # Move finished folders into your Plex/Jellyfin library
medianame namecheck [<path>]     # Read-only audit of an existing library
medianame healthcheck            # Verify config, TMDB token, paths, deps
medianame setup                  # (Re)configure API keys, paths, preset
medianame help                   # Show detailed help

Scan mode (v1.2.0+)

If you already have raw downloads like Movie.2011.2160p.BluRay.x265-SceneGROUP.mkv or folders like TV.Show.S01.1080p.REMUX-SceneGROUP/, scan mode parses the release names, looks each title up on TMDB with confirmation, creates the correctly-named library folder, and moves (or copies) the relevant media files into it.

medianame scan                         # Interactive: pick movie / series / custom path
medianame scan ~/Downloads             # Scan a specific folder
medianame scan --copy <path>           # Keep the source (default is move)
medianame scan --max-age-days 7 <path> # Only look at entries modified in the last 7 days

When scan can't resolve an entry (e.g. a Download Station folder or a one-off mystery filename), you get a three-way prompt before it's skipped:

  • [i] Add to ignore list β€” the name is persisted to your config's scan_ignore and skipped on every future scan, no extra setup required.
  • [m] Enter title manually β€” useful when the parsed release name is wrong and you want to tell medianame the real title.
  • [s] Skip (this run only) β€” default when you just press Enter.

What gets picked up:

  • Videos (.mkv .mp4 .avi .m4v .mov) β€” only files above the configured minimum size are kept, so samples, trailers, and extras are filtered out. The threshold defaults to 500 MB and can be changed in medianame setup (step 8).
  • All subtitle files (.srt .ass .sub .idx .vtt) β€” every language is preserved
  • Filenames are kept as-is; only the enclosing folder gets renamed
  • TV episodes land in Season NN/ subfolders based on the parsed season number
  • If a destination file already exists, you're prompted per conflict: skip / overwrite / abort

After a successful move, the original source folder is deleted along with any leftovers inside it (NFOs, screenshots, sample subfolders, …). The upfront confirmation prompt covers both the move and the cleanup in one step. When the operation is copy, the source is always preserved.

What is automatically skipped so scans on large library volumes stay fast:

  • Folders that already carry a medianame ID tag ({imdb-…}, {tmdb-…}, [imdbid-…], [tmdbid-…]) β€” they're assumed to be processed
  • OS / NAS metadata: #recycle, @eaDir, .Trash, lost+found, System Volume Information, $RECYCLE.BIN, .DS_Store, …
  • Anything you add as an extra ignore (setup step 9)
  • Subfolders deeper than 2 levels inside a scan item (scene releases never nest deeper)
  • Entries older than the configured max age, when set (setup step 10 or --max-age-days N)

The default operation (move or copy) is set during medianame setup (step 7) and can be overridden per run with --copy / --move. The default max-age is step 10 and can be overridden with --max-age-days.

Note on title matching. TMDB search is driven only by the parsed title; the parsed year is used to re-rank results (preferring the matching year, then Β±1). Appending the year to the query string would confuse TMDB's multi-search and return zero hits for otherwise obvious titles.

Publish to library (v1.3.0+)

If you keep a separate working area (where medianame creates folders) from your Plex/Jellyfin library root (what Plex actually indexes), publish automates the last step: moving the finished, tag-named folders into the library.

Configure it during medianame setup:

  • Step 11 β€” Movie library folder (e.g. /Volumes/Plex/Movies)
  • Step 12 β€” TV show library folder (e.g. /Volumes/Plex/TV)

Leave empty to disable. When at least one of them is set, every successful medianame scan runs an interactive publish step at the end (suppress with --no-publish, force with --publish). Or run it manually:

medianame publish               # Publish everything from both staging folders
medianame publish ~/Downloads   # Publish tag-named folders from a specific path

Only folders carrying a medianame ID tag ({imdb-…}, {tmdb-…}, [imdbid-…], [tmdbid-…]) are considered β€” untagged content in the staging area is left alone.

Conflict handling. Three cases trigger a prompt during publish:

  • Same-name file in target folder. Shown side-by-side with filename, size, and modified date. Options: [r] replace, [s] skip, [b] keep both (new file gets (1) suffix), [a] abort.
  • Different filename, but target already has a video. Same comparison display. [r] replace all existing videos with the new one, [s] skip the new file, [b] keep both, [a] abort.
  • Similar library folder with a different ID tag (or no tag). Four explicit options:
    • [1] Rename library folder to new, keep old files (discard new)
    • [2] Rename library folder to new, replace with new files (discard old)
    • [3] Rename library folder to new, keep all files
    • [4] Skip (leave both as-is)

TV series specifics. When a show already exists in the library:

  • New seasons are added without asking.
  • Existing seasons are merged episode-by-episode with the same same-name conflict prompt.
  • If the new episode uses a different naming scheme than existing episodes in the season (e.g. Show - S04E05.mkv vs. Show.S04E05.mkv), you're warned and can keep the new name, skip, or abort.

Progress indicator. Cross-filesystem copies of files β‰₯ 100 MB show a per-file progress line (Copying foo.mkv … 4.2 / 45.1 GB (9%)). Same-filesystem moves are instant renames and skip the indicator.

Staging cleanup. After a successful publish, the staging folder is removed if empty. If some files stayed behind (skipped conflicts, leftover .nfo files, samples) you get a summary listing and a prompt whether to delete anyway.

Library audit (v1.5.0+)

Two read-only commands help you keep an existing library clean without touching any files:

medianame namecheck [<path>] β€” audit one or both library roots and flag folders that don't follow medianame conventions. When no path is given, the configured library folders (movie_library_path / series_library_path from setup steps 11/12) are scanned β€” these are what Plex/Jellyfin actually indexes. If no library paths are set, the working folders are used as a fallback. Reports:

  • Folders without a medianame ID tag (Inception (2010) with no {imdb-…} / [imdbid-…])
  • TV seasons whose episode count doesn't match TMDB (missing episodes)
  • Orphan subtitle files (.srt with no matching video in the same folder)
  • Duplicate IDs β€” the same tt… / TMDB ID appearing in two folders

After the report, namecheck offers an interactive remediation loop. For each finding you can choose:

  • [f] fix β€” for missing tag: search TMDB, confirm a match, rename the folder in place. For orphan subtitle: delete the file. (Not available for season gaps or duplicate IDs β€” those need a human decision.)
  • [i] ignore permanently β€” persist the folder name to namecheck_ignore in your config. Future runs silently skip it.
  • [s] skip this run β€” default (press Enter). Nothing changes.
  • [a] abort β€” stop the loop and leave the rest untouched.

medianame healthcheck β€” smoke-test your installation:

  • Config file present and parseable
  • TMDB token accepted by the API
  • Configured paths exist and are writable
  • Optional library paths (when set)
  • guessit dependency importable
  • Legacy omdb_api_key detected (v1.4.0+ ignores it)

Use this right after medianame setup to verify everything is wired up, or to diagnose problems before filing a bug report.

Input formats

In interactive mode, you can enter:

Input Result
breaking bad Title search (movies + TV via TMDB)
https://www.imdb.com/title/tt1375666/ Direct IMDb URL β†’ movie
tt1375666 IMDb ID β†’ movie
https://www.themoviedb.org/tv/1396-breaking-bad TMDB URL β†’ TV show

Batch mode

Create a text file with one IMDb URL or tt-ID per line:

https://www.imdb.com/title/tt0133093/
https://www.imdb.com/title/tt1375666/
tt0167260

Then run:

medianame -f movies.txt

Successfully processed entries are automatically removed from the file (a .bak backup is created).

How it works

  1. Title search uses TMDB's /search/multi endpoint β€” one search returns both movies and TV shows
  2. Movies are tagged with the preferred ID format ({imdb-...} / [imdbid-...] / [tmdbid-...])
  3. TV shows are tagged with the preferred ID format and get Season subfolders
  4. When Jellyfin + TMDB movie IDs are requested from an IMDb input, /find resolves IMDb β†’ TMDB
  5. When Jellyfin + IMDb TV IDs are requested, external_ids on TMDB provides the IMDb ID
  6. Folders are created directly in your configured library paths

Upgrading

From an earlier medianame release

cd ~/Desktop/IMDB   # or wherever your clone lives
git pull
pipx install -e . --force     # --force picks up new dependencies

New config fields introduced in later versions fall back to sensible defaults β€” your existing config continues to work. Run medianame setup to adjust them interactively. Recent additions:

  • v1.2.0 β€” default_operation, min_video_size_mb
  • v1.2.1 β€” scan_ignore (extra ignores on top of built-in defaults)
  • v1.2.2 β€” scan_max_age_days
  • v1.3.0 β€” movie_library_path, series_library_path (optional publish targets)
  • v1.4.0 β€” OMDb API is no longer used; the legacy omdb_api_key in existing configs is ignored and can be removed
  • v1.5.0 β€” no new config fields; adds namecheck + healthcheck commands
  • v1.5.1 β€” namecheck_ignore (persisted per-folder skip list used by namecheck)

From plexname (v1.0)

medianame v1.1 is the renamed successor of plexname v1.0. If you had v1.0 installed:

pipx uninstall plexname
cd ~/Desktop/IMDB
git pull
pipx install -e .

Your existing ~/.config/plexname/config.json is automatically migrated to ~/.config/medianame/config.json on first run. Plex naming is the default, so your existing folders continue to work without changes.

API key

medianame uses a single free API:

  • TMDB API β€” for title search, movie and TV show lookups (by title or IMDb ID), and cast info. Free for non-commercial use.

Dependencies

Runtime dependencies (installed automatically by pip / pipx):

  • requests β€” HTTP client for the TMDB API (Apache 2.0)
  • guessit β€” parser for scene-style release filenames, used by medianame scan (LGPL-3.0; pure Python)

License

MIT

About

CLI tool to create Plex-compatible folder structures for movies and TV shows

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages