WP Manifestindependent plugin directory
manifest / unclassified / media-cleanup-scanner

Media Cleanup Scanner

Find and remove unused media, detect duplicates, optimize images, and clean unregistered files.

★ 0stars

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/labanthegreat/media-cleanup-scanner/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.

Scans the WordPress media library to find unused attachments, duplicate files, unregistered uploads, and broken media references. Provides bulk cleanup tools, image optimization, and scheduled background scanning.

Requirements

  • WordPress 6.0 or later
  • PHP 8.0 or later
  • GD library (required for image optimization and visual duplicate detection)

Installation

  1. Upload the media-cleanup-scanner directory to wp-content/plugins/.
  2. Activate through Plugins in the WordPress admin.
  3. Access the scanner from the Media Cleanup menu in the admin sidebar.

Features

Unused Media Detection

Scans post content, post meta, featured images, WooCommerce product galleries, ACF fields, customizer settings, shortcodes, and CSS background images to build a reference index. Any attachment not referenced anywhere is flagged as unused.

Duplicate Detection

Finds duplicate media using four methods:

  • Hash -- exact MD5 file hash comparison
  • Size -- same file size, verified with partial hash
  • Filename -- normalized filename similarity (configurable threshold, default 0.85)
  • Visual -- perceptual hash comparison for visually similar images (requires GD)

Duplicates can be merged: all references to the duplicate are rewritten to point to the original, then the duplicate is optionally deleted.

Unregistered File Detection

Scans the wp-content/uploads directory for files that exist on disk but have no corresponding attachment post in the database.

Broken Media Detection

Identifies four types of broken media:

  • Attachments whose physical files are missing from disk
  • Missing or ungenerated thumbnail sizes
  • Zero-byte (corrupt) files
  • Broken image/link URLs in post content pointing to the uploads directory

Missing thumbnails can be regenerated from the original file.

Image Optimization

Compresses images using the GD library with three quality presets:

Preset JPEG PNG WebP
Lossless 95 9 95
Balanced 82 6 80
Aggressive 65 3 60

Additional options:

  • Resize to maximum dimensions (default 2560x2560)
  • Convert to WebP format
  • Strip EXIF metadata
  • Thumbnails are regenerated after optimization

Supported formats: JPEG, PNG, WebP. GIF files are skipped (may be animated).

Scheduled Scanning

Automated scans via WP-Cron with daily or weekly frequency. Configurable options:

  • Email scan reports to a specified address
  • Auto-trash unused items older than a configurable threshold (30, 60, or 90 days)
  • Safe mode (suggest only, never auto-delete)

Cleanup Operations

  • Trash or permanently delete unused attachments (individually or in bulk)
  • Delete unregistered files from disk
  • Whitelist/ignore list to exclude specific attachments from scan results
  • Undo support for the last trash operation
  • Dry-run mode for previewing actions without making changes
  • Export unused media list as CSV
  • Reference cleanup on deletion (removes <img> tags, Gutenberg image blocks, _thumbnail_id meta, and WooCommerce gallery references)

Admin Interface

Multi-tab interface at Media Cleanup with the following tabs:

  • Dashboard -- storage summary, media type breakdown chart, monthly upload trends, quick action buttons
  • Unused Media -- grid/list view of unused attachments with bulk actions
  • Duplicates -- grouped results with side-by-side comparison and merge
  • Optimizer -- compression settings and bulk optimization with progress tracking
  • Unregistered -- orphaned file list with bulk delete
  • Settings -- scheduled scan configuration, auto-cleanup, safety, and duplicate detection threshold

WP-CLI Commands

All commands are registered under the wp media-cleanup namespace.

Scan for unused media

wp media-cleanup scan [--format=<format>] [--limit=<number>]

Lists all unused attachments with ID, filename, size, MIME type, and date.

  • --format=<format> -- Output format: table (default), csv, json, count
  • --limit=<number> -- Maximum results to return (0 = unlimited, default)
wp media-cleanup scan --format=csv
wp media-cleanup scan --limit=50

Delete unused media

wp media-cleanup delete --unused [--dry-run] [--force] [--yes]
  • --unused -- Required. Targets unused attachments.
  • --dry-run -- Preview what would be deleted without making changes.
  • --force -- Permanently delete instead of trashing.
  • --yes -- Skip the confirmation prompt.
wp media-cleanup delete --unused --dry-run
wp media-cleanup delete --unused --force --yes

Find duplicates

wp media-cleanup duplicates [--method=<method>] [--threshold=<threshold>] [--format=<format>]
  • --method=<method> -- Detection method: hash, size, filename, visual, all (default)
  • --threshold=<threshold> -- Similarity threshold for filename matching, 0.0-1.0 (default 0.85)
  • --format=<format> -- Output format: table (default), csv, json
wp media-cleanup duplicates --method=hash
wp media-cleanup duplicates --method=visual --threshold=0.90

Optimize images

wp media-cleanup optimize [--quality=<quality>] [--max-width=<pixels>] [--max-height=<pixels>] [--webp] [--strip-exif] [--limit=<number>] [--dry-run]
  • --quality=<quality> -- Preset: lossless, balanced (default), aggressive
  • --max-width=<pixels> -- Maximum width in pixels (default 2560)
  • --max-height=<pixels> -- Maximum height in pixels (default 2560)
  • --webp -- Convert images to WebP
  • --strip-exif -- Remove EXIF metadata
  • --limit=<number> -- Limit number of images to process
  • --dry-run -- Show what would be optimized
wp media-cleanup optimize --quality=aggressive --webp
wp media-cleanup optimize --quality=lossless --strip-exif --limit=100

Media library statistics

wp media-cleanup stats [--format=<format>]

Shows total attachments, disk usage, optimization stats, and MIME type breakdown.

  • --format=<format> -- Output format: table (default), json, yaml
wp media-cleanup stats --format=json

Find unregistered files

wp media-cleanup unregistered [--format=<format>] [--delete] [--dry-run] [--yes]

Lists files in the uploads directory that have no attachment post.

  • --format=<format> -- Output format: table (default), csv, json, count
  • --delete -- Delete the unregistered files
  • --dry-run -- Preview deletions without making changes
  • --yes -- Skip the confirmation prompt
wp media-cleanup unregistered
wp media-cleanup unregistered --delete --dry-run
wp media-cleanup unregistered --delete --yes

Options

The plugin stores its configuration in the following wp_options keys:

Option Key Description
mcs_scheduled_settings Scheduled scan configuration (enabled, frequency, email, auto-trash)
mcs_similarity_threshold Filename similarity threshold for duplicate detection (float)
mcs_whitelist Array of attachment IDs excluded from scan results
mcs_last_action Last trash action data for undo support
mcs_retention_policy Retention policy settings (enabled, days, action)
mcs_optimization_log Log of image optimization results
mcs_scan_history History of scheduled scan reports (up to 50)
mcs_media_stats Transient cache for media library statistics

Screenshots

Dashboard Dashboard with media stats, disk usage, type breakdown chart, and monthly upload trends

Settings Settings with scheduled scans, auto-cleanup, safety mode, and duplicate detection threshold

Changelog

3.0.0

  • Refactored to namespaced architecture (Jestart\MediaCleanup)
  • Added AJAX-driven admin interface with tabbed layout
  • Added broken media detection (missing files, missing thumbnails, zero-byte files, broken URLs)
  • Separated AJAX handling into dedicated Ajax_Handler class
  • Added PSR-4 style autoloader

2.1.0

  • Added broken media detector
  • Added safe delete mode (trash instead of permanent delete)
  • Added stats cache invalidation on attachment changes

2.0.0

  • Added WP-CLI commands (scan, delete, duplicates, optimize, stats, unregistered)
  • Added duplicate detection (hash, size, filename, visual)
  • Added smart merge for duplicates with reference rewriting
  • Added image optimization with quality presets, WebP conversion, EXIF stripping
  • Added scheduled scanning with email reports and auto-trash
  • Added whitelist/ignore list
  • Added undo support for trash operations
  • Added CSV export for unused media
  • Added retention policy settings
  • Deep scanning for WooCommerce galleries, ACF fields, customizer, shortcodes

1.0.0

  • Initial release
  • Unused media scanning with batched queries
  • Unregistered file detection
  • Trash and permanent delete support
  • Dry-run mode
  • Admin page under Media menu

License

GPL-2.0-or-later

Author

Laban The Great