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.
$ 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
medianame supports two naming presets:
Plex β naming docs:
- Movies:
Title (Year) {imdb-ttXXXXXXX} - TV shows:
Title (Year) {tmdb-XXXXX}withSeason 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.
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).
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 helpIf 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 daysWhen 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'sscan_ignoreand 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 inmedianame 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.
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 pathOnly 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.mkvvs.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.
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 (
.srtwith 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 tonamecheck_ignorein 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)
guessitdependency importable- Legacy
omdb_api_keydetected (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.
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 |
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.txtSuccessfully processed entries are automatically removed from the file (a .bak backup is created).
- Title search uses TMDB's
/search/multiendpoint β one search returns both movies and TV shows - Movies are tagged with the preferred ID format (
{imdb-...}/[imdbid-...]/[tmdbid-...]) - TV shows are tagged with the preferred ID format and get Season subfolders
- When Jellyfin + TMDB movie IDs are requested from an IMDb input,
/findresolves IMDb β TMDB - When Jellyfin + IMDb TV IDs are requested,
external_idson TMDB provides the IMDb ID - Folders are created directly in your configured library paths
cd ~/Desktop/IMDB # or wherever your clone lives
git pull
pipx install -e . --force # --force picks up new dependenciesNew 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_keyin existing configs is ignored and can be removed - v1.5.0 β no new config fields; adds
namecheck+healthcheckcommands - v1.5.1 β
namecheck_ignore(persisted per-folder skip list used bynamecheck)
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.
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.
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)
MIT