跳到正文
DEV Community· John Sheehy·· 2 小時前AI 評分42

Folio Refresh 如何在不損壞 Lightroom Classic 和 Capture One 目錄的情況下清理重複相片

Cleaning duplicate photos inside Lightroom Classic and Capture One catalogs without breaking them

AI 導讀

Folio Refresh 讀取 Lightroom Classic 和 Capture One 目錄中的編輯與評分資料,識別重複相片並標記建議移除的副本,不會直接刪除或搬移檔案。

正文

Disclosure: I'm the developer of Folio Refresh, the Mac app this post is about.

Most duplicate photo finders work on folders. Point them at a drive, they hash files, they move copies to the Trash. That is fine until the photos live in a Lightroom Classic or Capture One catalog. Delete a file behind Lightroom's back and the catalog shows a missing-photo badge; delete the wrong copy and you lose the edits, ratings and collections attached to it.

When I built Folio Refresh I wanted it to clean duplicates inside those catalogs, so here is how it does that without corrupting them.

Both catalogs are SQLite

A Lightroom Classic catalog (.lrcat) is a SQLite database. A Capture One catalog (.cocatalog) is a package with a SQLite database (.cocatalogdb) inside. Neither schema is documented, and both change between versions. That shapes every rule below.

Rule 1: read-only, always, while scanning

Scanning only ever opens the catalog read-only.

  • Lightroom: SQLITE_OPEN_READONLY. SQLite guarantees a read-only connection cannot write the database or its log, so this is safe even while Lightroom has the catalog open; it is just another reader.
  • Capture One: its database keeps no write-ahead log, so while Capture One is open it is read with ordinary shared locks, and while it is closed it is opened immutable.

Before reading anything, the app checks that every table and column it uses exists. If a new Lightroom or Capture One version renames something, the catalog is left alone instead of being read wrongly.

Rule 2: the catalog decides what is worth keeping

A folder can't tell you that one copy of a photo has two hours of Develop adjustments on it. The catalog can. When Folio Refresh groups duplicates, it reads what each copy carries:

  • Lightroom: pick flag, star rating, Develop adjustments, collections (including the Quick Collection), and virtual copies.
  • Capture One: rating, colour tag, adjustments, albums the person made, keywords, and variants.

A copy someone worked on is the one suggested to keep. A photo with a virtual copy (Lightroom) or a second variant (Capture One) is never offered for removal at all, because that "duplicate" is really another edit of the same file.

Rule 3: never delete. Mark, and let the app delete

Folio Refresh never deletes or moves a file inside a catalog. It changes exactly one thing, the same thing a person would change by hand:

  • Lightroom Classic: the duplicate's master image is marked Rejected, the same as pressing X. That is one column:
  UPDATE Adobe_images SET pick = -1.0
  WHERE id_local = ? AND masterImage IS NULL;

The person then runs Lightroom's own Delete Rejected Photos, which removes the photos from the catalog and the disk the way Lightroom expects.

  • Capture One: there is no Rejected flag, so duplicates are tagged Red, writing the colour tag to the same metadata rows Capture One writes when you press the Red tag yourself. The person filters by Red and deletes with Capture One's own Delete.

Marking frees no space by itself, and that is the point: the destructive step stays in the app that owns the catalog.

Rule 4: only write when the app is closed

Writing to a SQLite file another process has open is how catalogs get corrupted. So before any write:

  • Lightroom: no .lrcat-lock beside the catalog, and Lightroom Classic not running.
  • Capture One: not running, and no writelock file inside the package.

If either is open, nothing is written; the app asks you to quit it first.

Rule 5: back up with SQLite itself, then change everything in one transaction

Copying the .lrcat file with FileManager can miss pages still in the log. Instead the backup uses SQLite's online backup API, so the copy is a complete, consistent database:

guard let backup = sqlite3_backup_init(destination, "main", source, "main") else { throw ... }
let step = sqlite3_backup_step(backup, -1)   // copy every page
sqlite3_backup_finish(backup)

It lands in a Folio Refresh Backups folder beside the catalog, named with the date and never overwriting an earlier one. If the backup fails, nothing is changed.

Then all the marks go in one transaction (BEGIN IMMEDIATE … COMMIT, with ROLLBACK on any error), so a catalog is never left half-marked.

Rule 6: re-check right before writing, and keep an undo

Between review and cleanup, files can change. Right before marking, each duplicate must still be:

  • the same file the person reviewed, at the same path in the catalog,
  • not already Rejected (or Red, or in Capture One's Trash),
  • free of virtual copies or extra variants,

and at least one copy its group keeps must still be there, unchanged. Anything that fails is skipped with a reason.

Every mark is recorded with the flag it replaced, so Undo can put the old pick flag or tag back (again only while the app is closed), and the dated backup is always there as a last resort.

Rule 7: only write to versions you have tested

Reading works on any catalog whose columns check out. Writing is refused on a catalog version the app hasn't been tested against (Adobe_variablesTable.Adobe_DBVersion for Lightroom, ZVERSIONINFO.ZVERSION for Capture One). An undocumented schema is a moving target, and a refusal is cheaper than a broken catalog.

The rest of the app, briefly

  • Exact copies are found by SHA-256 of the file contents, so renamed copies match.
  • Similar shots use Apple Vision image feature prints, compared on the Mac, at three levels from near-exact to looser edits.
  • Bursts are grouped by capture time, with a keeper suggested by sharpness and Vision's aesthetics score.
  • Apple Photos duplicates go into a review album; deleting happens in Photos, which asks first.
  • Nothing is uploaded and there is no account.

If you keep a Lightroom or Capture One catalog and have opinions about how a tool should touch it, I'd like to hear them in the comments. Folio Refresh is free to scan and to clean your first 100 photos, then $14.99 once: caddora.ie/folio.

來源:DEV Community · dev.to