|
|
||
|---|---|---|
| .gitignore | ||
| calibre-manga-sorter.py | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
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 clonedownloads 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 namedcalibre-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/mediainside the box (the part after). Change/path/to/your/mediato where your libraries actually live. The trailing:romounts 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
:rois 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). Change1000:1000to 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 asD:/Media(forward slashes) or//d/Media. - macOS/Linux: something like
/Volumes/mediaor/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
idin a terminal — it prints youruid=andgid=numbers, e.g.1000:1000. - A NAS: the user/group numbers are usually shown in the user-management settings, or run
idover SSH. - Not sure?
1000:1000is 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.jpgnext 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.