Skip to content

WP-CLI plugin to clean orphaned media files

License

Notifications You must be signed in to change notification settings

built-fast/wp-cli-lost-and-found

Repository files navigation

wp-cli-lost-and-found

Warning

This package is in early development and may break your website or cause data loss. Use with caution and test thoroughly before running on production sites.

Detect and remove orphaned files in WordPress uploads directories.

Scans the uploads directory and cross-references against the WordPress attachment database to identify files not tracked as media library items. Supports local filesystem scanning and S3 object listings.

The problem

WordPress stores uploaded media as files in wp-content/uploads/ and tracks each one as an attachment post in the database. Over time, the two get out of sync: attachments get deleted through the admin but their files stay on disk, plugins drop temporary or generated files into uploads, and files land there via FTP or deployment scripts without ever being registered in the media library. The result is a steadily growing pool of orphaned files that waste storage, inflate backups, and make it harder to audit what's actually in use.

There's no built-in way to reconcile the filesystem against the database. This plugin scans every file in uploads, checks whether it belongs to a known attachment (including thumbnails, scaled originals, and editor variants), and reports or removes anything that doesn't.

Requirements

  • PHP 8.1+
  • WP-CLI 2.12+

Installation

wp package install built-fast/wp-cli-lost-and-found

Or load directly:

wp --require=wp-cli-lost-and-found-command.php media find-orphans

Commands

wp media find-orphans

Scan for orphaned files without modifying anything.

# JSON output (default)
wp media find-orphans

# Human-readable table
wp media find-orphans --format=table

# Scan S3 object listing
wp media find-orphans --file-list=/tmp/s3-objects.txt

# Custom exclude directories
wp media find-orphans --exclude-dirs=cache,woocommerce_uploads,gravity_forms
Option Default Description
--format=<format> json Output format: json or table
--exclude-dirs=<dirs> cache Comma-separated directory names to skip
--file-list=<path> Path to file listing (enables S3 mode)

wp media remove-orphans

Remove orphaned files from the uploads directory.

# Preview what would be removed
wp media remove-orphans --dry-run

# Remove orphans (with confirmation prompt)
wp media remove-orphans

# Remove without confirmation
wp media remove-orphans --yes

# Move to quarantine directory instead of deleting
wp media remove-orphans --yes --quarantine-dir=/tmp/quarantine

# JSON output for scripting
wp media remove-orphans --yes --format=json
Option Default Description
--dry-run false Show what would be removed, touch nothing
--yes false Skip interactive confirmation
--quarantine-dir=<path> Move files here instead of deleting; preserves directory structure
--format=<format> table Output format: json or table
--exclude-dirs=<dirs> cache Comma-separated directory names to skip

What gets detected

  • Files left behind after attachments are deleted from the database
  • Files uploaded via FTP/SFTP never registered in the media library
  • Plugin artifacts in uploads (Gravity Forms, Elementor, WooCommerce, etc.)

What is always tracked (never reported as orphans)

  • Original attachment files
  • All thumbnail/size variants from attachment metadata
  • WP 5.3+ scaled originals (original_image)
  • WordPress image editor variants (-e{timestamp} files)
  • PDF-generated preview thumbnails

What is always excluded

  • index.php and .htaccess files
  • Files inside directories specified by --exclude-dirs

Development

composer install

# Unit tests
composer phpunit

# Integration tests (requires MySQL)
composer prepare-tests
composer behat

# All tests
composer test

License

MIT

About

WP-CLI plugin to clean orphaned media files

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published