Reorganising a Lightroom catalog from the command line
A CLI utility that batch-renames folder hierarchies, moving folders on disk and updating the SQLite catalog in a single transaction so Lightroom sees the new paths without re-importing.
Lightroom Classic stores its catalog in a SQLite database. The application handles day-to-day usage well — but for some operations the GUI is genuinely hopeless. Try renaming 2024/2024-04-15/ to 2024/04/15/ across a thousand folders and you’ll see what I mean: drag folders one at a time, no batch rename, no preview. lightroom-catalog-tools is a small set of CLI utilities that work directly against the catalog and the filesystem, with a few rules I committed to from the start.
Preview, then apply
The default workflow is --dry-run first, no-flag second. The dry run prints a plan: which directories will be created, which folders will be moved, how many files in each, totals. Nothing changes on disk or in the catalog until --dry-run is removed.
A tool that can lose data without an obvious “what just happened” needs a preview as its default mode rather than as a flag people remember to set.
Atomic move-on-disk and catalog-update
Renaming folders in Finder and letting Lightroom catch up means a “missing folder” dialog for each one. The point of working directly against the SQLite catalog is that the catalog and the filesystem stay in sync — when the move succeeds, the catalog already knows.
Each folder operation moves on disk and updates the catalog in a single transaction. If either side fails, both roll back, and Lightroom sees a consistent state with no relinking needed.
Two layers of rule complexity
Most renames are simple: YYYY/YYYY-MM-DD/ → YYYY/MM/DD/. For those, a small placeholder DSL covers it — {year}, {month}, {day}, plus arbitrary {name} capture, with backreferences when a placeholder repeats.
For genuinely complex patterns there’s --regex, which switches the match side to raw regex with numbered capture groups. The DSL doesn’t try to grow into regex’s expressiveness; the regex flag is the escape hatch when it’s needed.
Was it worth it?
The catalog is SQLite, which means the operations the GUI doesn’t expose are reachable directly once the schema is understood. The repo is single-purpose for now and grows naturally each time I run into the next thing the GUI can’t do.
dmorel69/lightroom-catalog-tools— Python, SQLite