Duplicates, and setting things aside
VergeLabs Library → Duplicates.
Two features live here. One finds copies of the same picture. The other lets you retire a file without deleting it.
Finding duplicates, two ways #
An md5 of the file finds the byte-identical re-upload — the same file dragged in
twice, logo.png and logo-1.png.
A dHash finds the same photograph exported again at a different size or quality, where the bytes differ completely. The picture is reduced to 9×8 greyscale pixels and each pixel is recorded as brighter-or-not than the one beside it, giving a 64-bit fingerprint stored as 16 hex characters. Two images within a Hamming distance of 5 are treated as near-duplicates.
Both hashes are stored in attachment meta (_vergeml_hash) so the comparison is
done once.
What the dHash deliberately skips #
A 9×8 reduction answers confidently and wrongly for some images, so those are excluded from near-duplicate matching rather than reported as false pairs:
- images smaller than 64 pixels on a side — icons, spacers, tracking pixels
- fingerprints with too little variation across them: a flat colour, a plain gradient, a blank scan. One of them looks like every other at that resolution.
The md5 path still catches those when they really are identical.
Tidying #
When you tidy a duplicate set, the plugin picks the copy to keep by asking what is actually pointing at each one:
- The copy something references wins.
- If nothing references any of them, the oldest wins.
The rest are set aside, not deleted.
Repointing #
Deleting a duplicate yourself, from this screen, repoints everything that used it onto the survivor:
| Where a reference can hide | How it is repointed |
|---|---|
Post content — <img>, wp-image-N classes | URL stem and id replaced |
| Featured images | _thumbnail_id updated |
| URL-bearing post meta | URL stem replaced |
Builder layouts — _elementor_data, _fl_builder_data | URL stem and "id":N in their JSON |
| WooCommerce product galleries | _product_image_gallery, a comma list of ids |
| ACF image fields | Fields that store a bare id |
That list is the honest one. A reference in a place none of those covers — a hard-coded path in a theme file, for instance — is not repointed, which is one more reason the default action is to set aside rather than delete.
The scan #
Hashing runs in batches of 25 attachments, capped at 200 per request, so it cannot time out on shared hosting. It reports progress and resumes where it stopped.
Set aside, which is not deleting #
WordPress hard-deletes attachments. wp_delete_attachment() unlinks the file, and
MEDIA_TRASH is off by default. So "this file appears unused" plus a delete button
is a permanent action taken on the strength of a scan that can only ever say I did
not find a reference in the places I looked.
This feature exists so that button does not.
Setting aside is a mark, not a move. The file stays exactly where it is — same bytes on disk, same URL, same attachment id. It is hidden from the media library and listed on a screen of its own. Anything still using it goes on working. If a theme the scan cannot read is showing that photo, setting it aside breaks nothing and you find out.
Nothing may be considered for removal for thirty days. That is a floor, not a setting. The evidence for "unused" is absence, and absence is disproved by somebody noticing, which takes weeks rather than minutes.
There is a manifest. Every file set aside, with its id, title, path, size, and the reason it was set aside — downloadable as a file. A list you can check against a backup is the difference between a decision and a leap.
Taking something back is one click, always, at any point.
There is no delete #
The feature contains no call to wp_delete_attachment(), no unlink(), and no
file removal of any kind. There is no delete button and no delete endpoint. When
thirty days are up, the screen says the file is now eligible and hands you the
manifest. Removing media stays something you do yourself, in WordPress, having
looked.
You can verify this: the file is core/quarantine.php in the plugin source, and
the plugin is GPLv2.
Related meta keys #
| Key | Written by | Holds |
|---|---|---|
_vergeml_hash | Duplicate scan | md5 and dHash |
_vergeml_unused | Library scan | 1 if no reference was found |
_vergeml_used_in | Library scan | The post ids that reference the file |
_vergeml_filesize | Library scan | Size in bytes, for Large files |
_vergeml_quarantined | Set aside | Timestamp it was set aside |
_vergeml_quarantine_why | Set aside | The reason recorded at the time |
See Data model.
Written from version 3.15.0 of the plugin. Last updated 2026-10-02. All documentation · Legal · Support