Sort a Calibre library export into Komga-ready manga series folders
Find a file
xenarathon 3c1ee80437 Dockerfile: correct license label to GPL-3.0-or-later (matches LICENSE)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:31:53 -04:00
.gitignore calibre-manga-sorter: pull manga out of a Calibre library into Komga layout 2026-06-13 16:07:52 -04:00
calibre-manga-sorter.py Relicense from MIT to GPL-3.0-or-later 2026-06-13 18:57:48 -04:00
Dockerfile Dockerfile: correct license label to GPL-3.0-or-later (matches LICENSE) 2026-06-15 22:31:53 -04:00
LICENSE Relicense from MIT to GPL-3.0-or-later 2026-06-13 18:57:48 -04:00
README.md README: beginner-friendly rewrite with collapsible explainers + personalization steps 2026-06-15 22:28:55 -04:00

calibre-manga-sorter

Pull manga (.cbz/.cbr) out of a messy Calibre-style eBook library and reorganise it into a Komga-friendly "one folder per series" Manga library.

Calibre stores everything as Author/Title (id)/file, so manga added to it ends up scattered by author with truncated, subtitle-based folder names — and different volumes of the same series can even collapse to the same filename. For every comic archive it finds, this tool groups it by series, tells Japanese manga apart from Western comics, renames volumes to a tidy <Series> v##.ext so they sort correctly, and moves the manga into <MANGA_DEST>/<Series>/.

It defaults to a safe preview (DRY_RUN=1 — changes nothing, just prints what it would do), never moves a file onto an existing one (it skips and logs instead), and only ever writes into your manga destination folder. It is, however, a one-shot manual tool that moves and deletes files — so always preview first. (Western comics it recognises as duplicates are deleted when you run for real; more on that below.)

New to all this? No problem. The Quick start below is a few copy-paste steps, and every step has a click-to-expand explainer telling you what the command does and why.


Quick start

The safest way to use it: run once in preview mode (changes nothing, just shows what it would do), read the output carefully, then run it for real.

First time using a terminal? Start here

A "terminal" is a window where you type commands instead of clicking buttons.

  • Windows: install Docker Desktop, then open PowerShell (search for it in the Start menu).
  • macOS: install Docker Desktop, then open Terminal (in Applications → Utilities).
  • Linux: you likely already have a terminal and may already have Docker.

To run a command, copy it, paste it into the terminal window, and press Enter. That's it. "Docker" is just a tool that runs this program in a tidy box so you don't have to install Python or anything else yourself.

1. Get the code and build the program

git clone https://github.com/you/calibre-manga-sorter.git
cd calibre-manga-sorter
docker build -t calibre-manga-sorter .
What did that do?
  • git clone downloads a copy of this project to your computer. Replace the URL with wherever you got this from (e.g. your own Forgejo/GitHub address).
  • cd calibre-manga-sorter ("change directory") moves you into the folder it created, so the next commands run in the right place.
  • docker build -t calibre-manga-sorter . packages the program into a runnable image named calibre-manga-sorter. You only need to do this once (or again after you edit the script).

2. Preview what it would do (changes nothing)

docker run --rm \
  -v "/path/to/your/media:/media:ro" \
  calibre-manga-sorter
What does this command do, piece by piece?
  • docker run — start the program in its tidy box, then throw the box away when done (--rm).
  • -v "/path/to/your/media:/media:ro" — connects a folder on your computer (the part before the :) to the location /media inside the box (the part after). Change /path/to/your/media to where your libraries actually live. The trailing :ro mounts it read-only — a belt-and-braces guarantee that a preview can't change anything. See Personalize it to your setup for how to find that path.
  • calibre-manga-sorter — the name of the program you built in step 1.

You don't have to pass DRY_RUN here — preview is the default. The output lists each series and the filename each archive would get, plus which Western comics it would delete. If it looks right, move on.

3. Run it for real

Once you're happy with the preview, add -e DRY_RUN=0 and drop the :ro so it can actually write:

docker run --rm \
  -e DRY_RUN=0 \
  --user 1000:1000 \
  -v "/path/to/your/media:/media" \
  calibre-manga-sorter
What changed, and what does `--user 1000:1000` mean?
  • -e DRY_RUN=0 — turns off preview mode. Now it moves manga and deletes recognised Western comics for real. Only do this after a preview you trust.
  • The :ro is gone from the mount, so the program is allowed to write.
  • --user 1000:1000 — runs the program as a specific user/group so the moved files end up owned by the right account (so Komga, Calibre, etc. can read them). Change 1000:1000 to the user/group that owns your media — see Personalize it to your setup.

After it finishes it prints a summary: how many manga files were moved, how many Western comics were deleted, and how many now-empty Calibre folders it cleaned up.

4. Tidy up afterward

A few things to reconcile once the move is done — see After running.


Personalize it to your setup

You only ever need to change a couple of things. Here's what and how.

Your media path — the folder that contains your eBook Library, Manga Library, and Comics Library folders. In every command above, replace /path/to/your/media with that path.

How do I find my media path?

It's the parent folder that holds your library folders. The tool expects three folders inside the mounted /media: eBook Library (source), Manga Library (destination), and Comics Library (only read, to recognise comics you already have). Examples of the parent path:

  • Windows: D:\Media → write it as D:/Media (forward slashes) or //d/Media.
  • macOS/Linux: something like /Volumes/media or /srv/media.
  • A NAS/server: the path as that machine sees it, e.g. /srv/mergerfs/media.

Tip: open the folder in your file manager and copy it from the address bar. If your folders are named differently, see the settings table below to point SRC / MANGA_DEST / COMICS_DEST at them.

The owner of your media (--user) — so moved files have the right ownership.

How do I find my uid:gid?

--user takes two numbers, uid:gid (user id and group id).

  • macOS/Linux: run id in a terminal — it prints your uid= and gid= numbers, e.g. 1000:1000.
  • A NAS: the user/group numbers are usually shown in the user-management settings, or run id over SSH.
  • Not sure? 1000:1000 is the common default for the first user on most systems.

If the destination isn't writable by that user you'll get a PermissionError — see Permissions for the run-as-root workaround.

The settings (environment variables) — all optional; the defaults match a library laid out as above.

Variable Default What it does
DRY_RUN 1 1/true = preview only (default), changes nothing. Set to 0 to actually move manga and delete Western comics.
SRC /media/eBook Library The source Calibre library it scans for .cbz/.cbr files.
MANGA_DEST /media/Manga Library Where it creates the one-folder-per-series manga layout.
COMICS_DEST /media/Comics Library Only read, never written. Used to recognise which titles are already comics so they're treated as Western, not manga.
How does it tell manga from Western comics — and what happens to the comics?

A file is treated as a Western comic (not manga) if its author is in a built-in list of known Western authors, its title matches Western-comic keywords (Spider-Man, Batgirl, Avengers, …), or a matching series already exists in your Comics Library. Those are assumed to be duplicates or unwanted trade-paperbacks and are deleted when you run with DRY_RUN=0.

The preview lists every file it classified as Western before deleting anything, so you can check the call. If you'd rather move them somewhere instead of deleting, edit the western handling in main() and the WEST_AUTHORS / WEST_KW heuristics near the top of calibre-manga-sorter.py.

What if Calibre truncated a folder name so the volume number is lost?

Volumes are renamed to a zero-padded <Series> v##.ext so Komga sorts them correctly. When the volume number can't be recovered from a truncated name, the file keeps its original name, and if two files would still collide the tool appends the Calibre id so every file survives uniquely. The run output notes how many files this affected.


Don't want to use Docker?

It's a single Python file (3.x, standard library only — no packages to install). Set the paths and run it directly:

SRC="/srv/media/eBook Library" \
MANGA_DEST="/srv/media/Manga Library" \
COMICS_DEST="/srv/media/Comics Library" \
DRY_RUN=1 python3 calibre-manga-sorter.py

Change DRY_RUN=1 to DRY_RUN=0 to apply, once the preview looks right.


How matching & naming works

A Calibre folder like Title, Vol. 3 (482) is reduced to its series and volume: the trailing Calibre id (482) is stripped, the text up to Vol. N / #N becomes the series, and a small list of overrides fixes series whose names Calibre split or truncated. The result is laid out as:

Manga Library/
├── Chainsaw Man/
│   ├── Chainsaw Man v01.cbz
│   ├── Chainsaw Man v02.cbz
│   └── Chainsaw Man v03.cbz
└── My Lesbian Experience With Loneliness/
    └── (original filename kept — no volume number to parse)

Files that already live where they'd be moved are skipped, not overwritten. After a real run, any Calibre folders left completely empty are removed automatically.


After running

  • Empty Calibre folders left behind are removed automatically.
  • Calibre keeps a metadata.opf + cover.jpg next to each book. This tool moves only the comic archives, so those sidecars — and the entries in your Calibre database (and anything reading it, e.g. Calibre-Web / LazyLibrarian) — remain until you reconcile Calibre separately.
  • Rescan Komga so it picks up the new series.

Permissions

If the destination library isn't writable by your media user you'll get a PermissionError. Either make the folder writable first, or run the tool as root (--user 0:0) and fix ownership afterward.

Run as root, then fix ownership
# run the move as root so it can always write:
docker run --rm -e DRY_RUN=0 --user 0:0 \
  -v "/path/to/your/media:/media" \
  calibre-manga-sorter

# then match the new files to whatever owns your other libraries, e.g. 1000:100:
docker run --rm --user 0:0 \
  -v "/path/to/your/media:/media" \
  --entrypoint sh calibre-manga-sorter \
  -c 'chown -R 1000:100 "/media/Manga Library" && chmod -R 775 "/media/Manga Library"'

Replace 1000:100 with the owner your other libraries use.


Good to know

  • It's a one-shot manual tool, not a scheduler. The delete-Western-comics behaviour makes unattended runs risky — run it by hand (preview, then apply) whenever you add manga to Calibre.
  • Classification is heuristic. The manga/comic split and series parsing can be wrong on ambiguous titles, which is exactly why preview defaults on. Read the output before applying.
  • Versions and already-placed files are safe — anything already sitting at its destination is skipped rather than overwritten.

License

GNU GPL v3 (or later) — see LICENSE. Copyleft, so derivatives stay free software.