Do You Need a Snippet to Clean WordPress Upload Filenames?

Date:

You upload Health & Safety Authority.JPG and wonder whether you need a snippet to fix the name. Most “rename uploads” snippets repeat work WordPress already does, and the ones that rebuild names from scratch can make some of them worse.

The short answer: WordPress already cleans upload filenames: it turns spaces into hyphens, drops symbols like &, % and brackets, strips accents and lowercases the extension. What it leaves alone is capital letters, a few characters such as the en dash, and non-Latin names. If you want lowercase names, a six-line filter on sanitize_file_name does it. A bigger snippet that rebuilds the name from scratch is where things go wrong.
Bar chart of upload filenames in one WordPress media library, 394 files in total. Underscores: 22 files. Capital letters: 14 files, the one trait that can break a link, because file addresses on most servers are case-sensitive. An extra dot inside the name: 1 file. Non-Latin characters: 0. Camera-default names such as IMG_1234: 0.

What WordPress does to upload filenames

Every upload passes through sanitize_file_name() before it’s written to disk. Eleven test files uploaded to a clean WordPress 7.0.2 test site show what that means in practice. Here is what core did on its own with eight of them:

Uploaded asWordPress stored
Health & Safety Authority.JPGHealth-Safety-Authority.jpg
IMG_2901 (1).pngIMG_2901-1.png
Résumé Final v2.PNGResume-Final-v2.png
my photo--final__.jpegmy-photo-final__.jpeg
100% done!.png100-done.png
file.name.with.dots.jpgfile.name_.with_.dots_.jpg
Café menu – summer.jpgCafe-menu-–-summer.jpg
製品写真.png製品写真.png

That covers most of what a rename snippet promises. Spaces and runs of hyphens collapse, the risky characters go (slashes, quotes, &, %, #, brackets), accented letters become plain ones, and .JPG becomes .jpg.

The odd-looking file.name_.with_.dots_.jpg is deliberate. WordPress puts an underscore after each extra dot so a name like photo.php.jpg can’t be treated as a script by a server that reads every extension. It can still catch you out: if a script or sync tool uploads x.cover.webp and later looks the file up by its exact name, it won’t find it, because WordPress stored x.cover_.webp. Use hyphens inside names (x-cover.webp) and the problem disappears.

WordPress already does most of what a rename snippet promises.

What core leaves alone, and whether it matters

Three things survive, and only one of them can cause a real problem.

Capital letters. Health-Safety-Authority.jpg keeps its capitals. File addresses are case-sensitive on most web servers, so a link typed as health-safety-authority.jpg returns a 404. That’s the one good reason to lowercase.

The en dash and non-Latin names. – and 製品写真 stay as they are, and in the address they become percent-encoded strings like %E2%80%93. Browsers handle that fine. It’s untidy when someone copies the link, and that’s all.

Underscores. IMG_2901 keeps its underscore. Google’s URL guidance prefers hyphens between words, but an underscore in a filename doesn’t break anything.

How often does each trait turn up? One real site’s media library, checked on 10 October 2026, held 394 files. Fourteen had a capital letter, 22 an underscore, one an extra dot. None had a non-Latin name, and none had a camera name like IMG_1234, because every image there was named before upload. Run the same count on your own library before deciding a snippet is worth adding.

Why a rebuild-from-scratch snippet backfires

A common style of “force clean filenames” snippet, often written for WordPress networks, rebuilds every name from scratch: lowercase, ASCII letters, digits and hyphens only, and a site-number prefix such as s2- on a multisite network. Testing one such snippet on a test site showed how it goes wrong:

Uploaded asWordPress aloneWith the rebuild snippet
Health & Safety Authority.JPGHealth-Safety-Authority.jpghealth-safety-authority-jpg.jpg
Résumé Final v2.PNGResume-Final-v2.pngresume-final-v2-png.png
製品写真.png製品写真.pngfile.png
s3-bucket-diagram.png (on site 2)s3-bucket-diagram.pngs2-bucket-diagram.png

Every upper-case extension doubled. The snippet lowercased the extension first and then asked PHP to cut that lowercase extension off the original name. .JPG isn’t .jpg, so nothing was cut, and the old extension became part of the name. Many cameras save photos with an upper-case .JPG, so this would have hit a lot of real uploads.

Non-Latin names vanished. Anything that wasn’t a Latin letter or digit was deleted, so a Japanese filename became file.png, and the next one would be file-1.png. WordPress on its own kept the original name.

The site prefix ate real words. To avoid stamping a file twice, the snippet removed any existing s + digits + hyphen from the start of a name. A diagram called s3-bucket-diagram.png lost its s3. The prefix was redundant anyway: a multisite network already stores each subsite’s uploads in their own folder (uploads/sites/2/ and so on).

Snippets like this are often sold on the claim that lowercase hyphenated names make the server faster and block directory-traversal attacks. Nothing backs either claim. A file’s name doesn’t change how fast the server finds it, and core already removes the slashes those attacks need.

The snippet’s worst bug hit the most common upload there is: a photo ending in .JPG.

The six lines that help

If you want lowercase names, add to what WordPress already did rather than replacing it. The sanitize_file_name filter receives the name after core has cleaned it:

// Runs after WordPress's own cleaning: lowercase the name and turn en/em dashes into hyphens.
add_filter( 'sanitize_file_name', function ( $filename ) {
    $filename = str_replace( array( "\u{2013}", "\u{2014}" ), '-', $filename );
    $filename = preg_replace( '/-{2,}/', '-', $filename );
    return strtolower( $filename );
} );
Code language: PHP (php)

On the test site, Health & Safety Authority.JPG became health-safety-authority.jpg, Café menu – summer.jpg became cafe-menu-summer.jpg, and the Japanese name and s3-bucket-diagram.png came through untouched. Add it as a code snippet or a small must-use plugin; it’s the kind of job a snippet handles better than a plugin.

It only affects new uploads. Renaming files already in your library changes their addresses, and every post that embeds them would need its links rewritten, the same search-and-replace job as a domain move. For a dozen or so files with capitals, that’s rarely worth it.

What no snippet can fix

A filter can tidy characters. It can’t turn IMG_2901.jpg into blue-ceramic-teapot.jpg, and that’s the part search engines can use: Google says a filename gives it light clues about what an image shows. Naming files for what they show happens before upload, by a person or by whatever tool prepares your images. If you keep a managed image library, naming files once in the library solves this for every upload that follows.

The short version

WordPress already strips spaces, symbols and accents from upload filenames and lowercases the extension. It keeps capitals, en dashes and non-Latin names. Capitals are the only one that can break a link. A six-line filter that lowercases what core produced fixes that; a snippet that rebuilds names from scratch can double extensions, erase non-Latin names and eat real words. Descriptive names still come from you.

Frequently Asked Questions

Why did WordPress add an underscore to my filename?

Your file had more than one dot in its name. WordPress adds an underscore after each extra dot (file.name_.jpg) so a name like photo.php.jpg can’t be run as a script on a server that reads every extension. Use hyphens instead of dots inside names and it won’t happen.

Will a filename snippet rename images I’ve already uploaded?

No. The filter runs when a file is uploaded, so existing files keep their names and addresses. Renaming them means moving the files and rewriting every link to them, so only do it if broken links are actually a problem.

Share post:

Subscribe

Popular

More like this
Related

Replace the WordPress Logo With Your Site Icon, Everywhere It Shows

Changing the login logo is the well-known fix. The WordPress mark also sits in the toolbar, the login popup, every tab title and the admin footer, and on a multisite network each site should show its own icon, not one shared logo.

How to Show a WordPress Shortcode Without Running It

You write a tutorial that mentions a shortcode in a code example, and the published page shows something else: a gallery, a block of other posts, or an empty gap where the example should be. WordPress ran the shortcode you were only trying to mention.

How to Customize the tagDiv Newspaper Theme When the Accent Color Won’t Change

You change the Newspaper theme's accent color in the Theme Panel, save, and the header, menu and footer are still the old red. Then you try to adjust the phone layout outside the Composer and find every setting stored as base64-encoded JSON. Both have a reliable fix, step by step.

How to Update Rank Math SEO Fields Through the REST API Without Exposing Your Focus Keywords

You send a meta description to a post's REST API endpoint, WordPress replies with HTTP 200, and the field in the Rank Math panel is still empty. One function call per field fixes the write. Done the obvious way, it also publishes every focus keyword you chose.