WP Manifestindependent plugin directory
manifest / media / simple-media-cleaner

Simple Media Cleaner

Wordpress Plugin: Clean unused images from WordPress site.

★ 0stars
v1.4.0latest · 7mo ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/rkalajian/simple-media-cleaner/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

A WordPress admin plugin that finds and permanently removes unused, unattached, and broken media — DB records, original files, and all WordPress-generated sizes in one pass.

Features

  • Batched library scan with live progress bar — handles large libraries without timeouts
  • Seven-point usage check verifies each attachment is genuinely in use before flagging it
  • Broken reference detection — flags DB attachment records whose file no longer exists on disk
  • Orphaned file detection — scans the uploads directory for files that have no DB record
  • Unattached only filter — limit scans to media with no parent post
  • Card grid UI with thumbnail previews, file type badges, and reason badges (Missing file / No DB record)
  • Multi-select with floating action bar
  • Confirmation modal listing files before deletion
  • Live stats: total scanned, removable count, missing file count, estimated disk savings

How it works

Scan (Phase 1 — Library) — Fetches attachments in batches of 100 via AJAX. Each batch runs two checks in parallel: a file_exists() pass that flags broken references immediately, and a call to tymc_filter_unused() that runs the seven-point usage analysis on healthy attachments. Both sets of results are returned as removable items.

Scan (Phase 2 — Filesystem) — After the library scan completes, the uploads directory is scanned recursively for media files not registered in the DB. Known paths (original files + all generated sizes from _wp_attachment_metadata) are excluded. Matches appear with a "No DB record" badge.

Delete — Selected items are sent in chunks of 50:

  • DB-backed items (unused + broken references): wp_delete_attachment( $id, true ) permanently removes the post row, all postmeta, the original file, and every resized variant — the item disappears from the Media Library immediately.
  • Orphaned filesystem files: deleted directly via unlink() after path validation (must resolve within the uploads directory and must not match a DB attachment record).

Usage checks

An attachment is considered in use if any of the following are true. All postmeta checks join against wp_posts so stale rows from deleted posts are ignored.

# Check Method
1 Has a post_parent pointing to a non-trashed, existing post Batch INNER JOIN
2 Used as a featured image (_thumbnail_id) on an active post Batch INNER JOIN
3 URL appears in any non-trashed post content Per-item LIKE query
4 Included in a WooCommerce product gallery on an active product Single query + PHP
5 Stored as a postmeta value (ACF image/file fields) on an active post Batch INNER JOIN
6 Set as site icon or custom logo get_option / get_theme_mod
7 URL or quoted ID appears in the options table Per-item LIKE query

License

Simple Media Cleaner is licensed under the GNU General Public License v2.0 or later (GPL-2.0+), in accordance with WordPress plugin licensing requirements.

Requirements

  • WordPress 6.0+
  • PHP 8.1+
  • delete_posts capability to access the page

Installation

Drop the simple-media-cleaner/ folder into wp-content/plugins/ and activate via Plugins → Installed Plugins. The tool appears under Media → Media Cleaner.

Changelog

1.5.0

  • Bug fix (critical): Checks 1, 2, 4, and 5 now INNER JOIN against wp_posts to verify the referencing post still exists and is not trashed or auto-draft. Previously, stale postmeta rows left behind when a post was permanently deleted kept attachments flagged as "in use" indefinitely — this was the primary reason unused media wasn't surfaced by the scanner.
  • New: Broken reference detection — attachments with a DB record but no file on disk are flagged with a "Missing file" badge and included in scan results. Deletion via wp_delete_attachment removes the dangling DB record, cleaning up the Media Library.
  • New: Orphaned file scan (Phase 2) — after the library scan, the uploads directory is recursively scanned for media files with no DB record. Orphan files appear with a "No DB record" badge and are deleted directly via unlink().
  • New: "Unattached only" checkbox — limits the scan to attachments with post_parent = 0 for faster targeted cleanup.
  • New: "Missing Files" stat counter — dedicated count of broken DB references found during the scan.
  • Fix: Progress bar total now sums all attachment statuses (not just inherit + 0) to prevent the bar exceeding 100% on some sites.
  • Refactor: itemById Map replaced with itemByKey supporting both ID-based (DB) and path-based (orphan) items.

1.4.0

  • Renamed plugin from WP Media Cleaner to Simple Media Cleaner

1.3.0

  • Fixed delete doing nothing for large selections: IDs are now sent in chunks of 50, staying well under PHP's max_input_vars limit
  • Deletion progress shown in the floating action bar so it remains visible regardless of scroll position
  • Progress bar fills per-chunk with file count and percentage; holds at 100% briefly before restoring the selection UI

1.2.0

  • Replaced per-attachment tymc_is_unused() with tymc_filter_unused() — batch DB queries reduce scan query count from ~6N to ~6–8 per 100-item batch
  • Fixed multi-file delete: URLSearchParams array serialization bug meant only the first selected ID was deleted
  • URL computed during content check is cached and reused for the options check
  • Added itemById Map for O(1) modal lookups; post-delete filtering uses a Set

1.1.0

  • Added WooCommerce product gallery check
  • Added options table check for ACF options fields
  • Added site icon and custom logo exclusions
  • Progress bar with shimmer animation

1.0.0

  • Initial release

Releases

1 release.

Tag
Published
v1.4.0 latest
Mar 18, 2026 7mo ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.