A couple of nights ago, my server monitoring fired off a disk space alert at 2 AM. When you have four kids waking up in a few hours, the last thing you want is a partition running low on space.
I hopped into SSH, ran ncdu /var/www/html/wp-content/uploads, and stared at the screen. The uploads directory had climbed to over 18 gigabytes, but the WordPress Media Library only showed about 800 images. Where did the rest come from?
If you run WordPress sites long enough—especially WooCommerce stores or client blogs migrated across hosts—you will hit this exact issue. Your disk fills with “ghost files” that WordPress does not even know exist.
Here is what causes them, why deleting files over FTP blindly is risky, and how we clean them up safely.
What Exactly Is an “Orphaned Upload”?
To understand why files get lost, you have to look at how WordPress tracks media under the hood.
When you upload an image in the WordPress admin:
- The physical file gets written to disk inside
/wp-content/uploads/YYYY/MM/. - WordPress generates various sub-sizes (thumbnail, medium, large) on disk.
- WordPress creates an entry in your database inside the
wp_poststable withpost_type = 'attachment'. - The attachment dimensions and sub-size filenames are stored inside
wp_postmetaunder_wp_attachment_metadata.
An orphaned upload happens when physical files sit in your uploads directory, but the database has zero record of them.
/wp-content/uploads/
├── 2024/05/product-photo.jpg <-- In wp_posts (Active Media)
├── 2024/05/product-photo-300x200.jpg <-- Registered sub-size (Safe)
└── 2024/05/abandoned-banner.jpg <-- No DB record (Orphan / Ghost File)
How does this happen? Usually:
- An upload stalled halfway through (browser crashed or PHP timed out).
- A media item was deleted from the admin, but a file permission glitch prevented PHP from unlinking the physical file on disk.
- A backup, staging import, or uninstalled plugin left temp files behind.
- You changed themes, and old custom image dimensions were abandoned on disk forever.
These ghost files do not just eat storage. Every time you run daily backups or rsync your site to a staging server, you are transferring dead weight.
Why You Shouldn’t Just rm -rf or FTP Delete Blindly
Back in my early twenties tinkering with 486 PCs and early Linux distros, I had a bad habit of running aggressive cleanup commands. I learned the hard way that brute force usually ends in reinstalling everything on a Saturday night.
You cannot simply sort files by date over FTP and delete old ones. An image uploaded back in 2018 might still be the primary logo on your homepage, or the featured image on your top-ranking blog post.
You need a tool that physically walks the uploads directory on disk, cross-references each file against active WordPress attachment records (including all registered thumbnails), and flags only the true orphans.
Why We Built CE Orphan
Most media cleanup plugins on the repository fall into two categories:
- They try to do too much—scanning every post content block, CSS file, and external CDN—which causes PHP timeouts and white screens on shared hosting.
- They choke when you try to bulk delete more than 25 files at once.
We built CE Orphan to be focused, safe, and fast. It does one specific job: it finds files sitting in wp-content/uploads/ that have zero attachment records in the WordPress database, lists them in a clean table, and lets you delete them in batches without crashing your server.
Here is what we baked into it:
- “Only Orphan” view by default: As soon as you open the page, you only see the files that can be safely cleaned up.
- Fast column sorting: Sort by file size so you can target massive multi-megabyte videos and raw PNGs first.
- Chunked batch deletion: Instead of sending 100 deletes in one giant request that hits PHP execution limits, it deletes in small, rapid 10-file chunks.
- Fixed-viewport progress bar: Even if you display 100 items per page and scroll down, the live progress modal stays centered right in front of you.
- Instant stop/cancel: If you change your mind mid-batch, clicking Stop cancels the request immediately.
- Strict safeguards: Core files like
.htaccess,index.php,web.config, and dynamic directories (Elementor styles, cache) are protected automatically.
Step-by-Step: How to Safely Clean Up Your Uploads
Let’s walk through cleaning up your uploads directory safely.
Step 1: Take a Quick Backup
Before you delete anything on a production server, always take a backup. I tell this to everyone just like my dad told me to disconnect the car battery before touching the alternator.
Use your hosting backup tool, UpdraftPlus, or run a quick tarball via terminal:
tar -czf uploads-backup-$(date +%F).tar.gz wp-content/uploads/
Step 2: Open CE Orphan
Install and activate the plugin, then go to Tools → CE Orphan in your WordPress dashboard.
The plugin scans your uploads directory and checks every file against your wp_posts and _wp_attachment_metadata tables.
The top summary cards will show:
- Total files on disk and total disk usage.
- Total orphaned files found.
- Total recoverable disk space.
Step 3: Sort by Size
By default, the Only Orphan switch is already toggled on.
Click the Size column header to sort in descending order. In most cases, 80% of your wasted space comes from a handful of uncompressed camera uploads, accidentally uploaded video clips, or failed ZIP archives.
Step 4: Delete a Test File First
Select one or two orphaned files and click the red Delete button. Verify that the deletion completes smoothly and the disk space is freed.
Step 5: Run Mass Deletion
Once you are confident:
- Check the Select All checkbox in the table header.
- Select Permanently Delete Selected from Bulk actions.
- Click Apply.
A progress modal will appear centered on your screen showing the percentage, file count, and recovered space. If you need to pause, click Stop / Cancel to halt immediately.
A Quick Note on File Permissions
If a file fails to delete during the process, it is almost always a Linux file permission mismatch. This happens often if you previously extracted a tar archive as root instead of the web server user (www-data or nginx).
If you run your own VPS, make sure your uploads folder is owned by the web server:
sudo chown -R www-data:www-data /var/www/html/wp-content/uploads/
sudo find /var/www/html/wp-content/uploads/ -type f -exec chmod 644 {} \;
sudo find /var/www/html/wp-content/uploads/ -type d -exec chmod 755 {} \;
Wrapping Up
Cleaning out orphaned files is one of the easiest ways to speed up your backups, keep hosting costs down, and maintain a tidy server.
You can download CE Orphan from the WordPress Plugin Directory or grab the code from our site. Give it a run on your site, and see how much space was hiding in your uploads folder.
Got questions or ran into an unusual file type? Leave a comment below and I will be glad to help troubleshoot.
No Comments