Duplicate + Photo Cleanup

DuplicateDeck

Finds invoice.pdf, invoice (1).pdf and invoice_final.pdf. Never opens a file.

Free right now — no account, no card

Get DuplicateDeck free Windows & Mac · one file, nothing to install

Preview

1 interface design, then a screenshot of it running. Drag, scroll or use the arrows.

Interface design DuplicateDeck, 1 of 1
Screenshot DuplicateDeck running on Windows today

Free while we’re in preview

Get DuplicateDeck

Finds invoice.pdf, invoice (1).pdf and invoice_final.pdf. Never opens a file.

The Mac button is for Apple Silicon. On an older Intel Mac, get this one instead.

One file, both ways. Double-click it for the window. Run the same file from a command prompt with arguments and it behaves as the command-line tool, because the engine is inside it. Nothing else to download and nothing to keep beside it.

Early preview. The window has been built and run, but not yet on a real Windows PC or Mac, so expect rough edges. The engine underneath it is fully tested.

  • One file — no installer
  • Runs on your machine, offline
  • Source code published below

Free while in preview. It isn’t signed yet, so Windows or macOS will ask you to confirm the first time you open it. At launch, DuplicateDeck is included in every plan along with the rest of the range.

Four files a content hasher cannot see

invoice.pdf, invoice (1).pdf, invoice_final.pdf, invoice - Copy.pdf. The same document to you. Four different SHA-256 values, because a re-download or a one-word edit changes the bytes, so a hash deduper reports nothing at all. DuplicateDeck comes at it from the other side. It strips copy markers off the name, lowercases what’s left, and measures the Levenshtein edit distance between the results.

Where it will bite you

IMG_4471.JPG and IMG_4472.JPG differ by one character. They score 0.875, they cluster at the default threshold, and they are two completely different photographs. Do not point this at a camera roll and reach for --apply. Same story for page 01.png, track 3.mp3 and invoice 2024-01.pdf. Raise --min-similarity, or use PhotoSweep, which compares the actual images.

Use compare first

duplicatedeck compare "invoice.pdf" "invoice (1).pdf" prints the edit distance, the marker difference and the resulting score, so you pick a threshold on evidence rather than vibes.

When you do apply

The largest file in a cluster is kept and a newer mtime breaks a tie. Everything else moves to a quarantine folder with its relative path intact. Nothing is overwritten, nothing is deleted, and emptying the quarantine is your call.

Reading on the job itself

Advanced & technical details Command-line builds, source code, checksums and a recorded session — for developers and IT teams

A working CLI prototype of the near-duplicate-name engine: real Levenshtein edit-distance clustering over normalised filenames, which catches the “invoice.pdf / invoice (1).pdf / invoice_final.pdf” families that content-hash dedup misses entirely because their bytes differ. Non-keepers are quarantined, never deleted. Note it will also cluster sequential camera filenames — the README says so plainly.

Recorded session

Recorded terminal session showing DuplicateDeck running
A real recorded session — DuplicateDeck’s actual output, captured by running the shipped binary.

What it draws on

Existing paid software whose best ideas shaped this program: Duplicate Cleaner Pro, Easy Duplicate Finder, TreeSize Professional, Advanced Renamer Commercial.

Command line

There is nothing extra to install. The program you download is the command-line tool as well: give it arguments instead of double-clicking it and it runs as one, with its output on your terminal. The standalone builds below are the same engine on its own, for machines where you would rather not ship a window at all.

DuplicateDeck 1.0.0 — find near-duplicate files by FILENAME similarity.

Content-hash dedupers miss "invoice.pdf / invoice (1).pdf / invoice_final.pdf"
families because the bytes differ. DuplicateDeck compares normalized filenames
with a real Levenshtein edit distance instead.

Usage:
  duplicatedeck scan <dir> [--min-similarity 0.8] [--json]
  duplicatedeck quarantine <dir> --quarantine <qdir> [--min-similarity 0.8] [--apply]
  duplicatedeck compare <nameA> <nameB> [--json]
  duplicatedeck help | -h | --help

Commands:
  scan        Walk <dir> recursively, cluster files whose normalized names are
              within the similarity threshold, and mark a suggested KEEPER
              (largest file; newest mtime breaks ties).
  quarantine  Move every non-keeper cluster member into <qdir>, preserving the
              path relative to <dir>. DRY RUN unless --apply is given.
              Files are MOVED, never deleted.
  compare     Show the normalization, raw Levenshtein distance and similarity
              of two names. Useful for choosing --min-similarity.

Flags:
  --min-similarity F   Cluster threshold in [0,1] (default 0.80).
  --quarantine DIR     Destination directory for the quarantine command.
  --apply              Actually move files. Without it, quarantine is a dry run.
  --json               Machine-readable JSON output.

Exit codes:
  0  success (including "nothing found")
  1  bad invocation or a fatal error

Recorded from the shipped binary, not written by hand.

Source

Every file the program is built from:

console.go · console_test.go · guided.go · main.go

SHA-256 checksums · build instructions & scope notes · full build plan