How to Sanitize a Filename: Make Any String a Safe Filename Everywhere
Learn the forbidden characters, reserved names, and trailing-dot traps that break filenames, and how to sanitize any string into a safe filename across Windows, macOS, and Linux.
How to Sanitize a Filename: Make Any String a Safe Filename Everywhere
A filename looks like the most trivial string in software. You take a title, stick an extension on the end, and write it to disk. Then a colon in the title kills a download on Windows, a scraped article name with a slash in it crashes a batch rename halfway through, and a file called NUL.log silently fails to extract from a zip on your teammate's laptop. None of these throw a clear error. They just quietly break, usually on a machine that isn't yours.
The rules that decide whether a string is a legal filename are old, inconsistent between operating systems, and mostly undocumented in the places people learn to code. This post walks through every category of trap, then shows how to turn a messy string into a name that saves on the first try anywhere.
The nine characters Windows forbids
Windows rejects nine printable characters anywhere in a filename, no matter the folder or extension:
\ / : * ? " < > |
Each one is a fossil from DOS. The colon meant a drive letter (C:), the asterisk and question mark were wildcards, the angle brackets and pipe were shell redirection, and the two slashes are path separators. The meanings are long gone, but the bans stayed. On top of those, Windows also rejects the control characters with code points 0 through 31 — the invisible bytes like null, tab, and the various line-ending characters that can sneak into a string copied from a PDF or a terminal.
macOS and Linux are far more relaxed. They reserve only two things: the forward slash, because it separates path components on every Unix-like system, and the null byte, which terminates a C string. So a:b*c.txt saves fine on a Mac and then refuses to save the moment someone opens that folder on Windows.
This asymmetry is the whole problem. A name that worked when you made it can be invalid the instant it crosses to another platform. If you ever zip a Mac folder for a Windows colleague, sync through a shared drive, or build software other people run, the safe move is to sanitize to the strict Windows rule from the start. The strictest rule is the only portable one.
Reserved device names that no folder can hold
This trap catches even careful people, because every character in the name is perfectly legal. Windows reserves a short list of old device names:
CON PRN AUX NUL COM1–COM9 LPT1–LPT9
You cannot save a file called CON.txt, or even just con, on any Windows machine. The OS interprets the base name as the console, a printer port, or a serial device, and refuses regardless of extension or folder. The check is case-insensitive, so Con, con, and CON are equally blocked. A plain character filter never catches this, because nothing in NUL.txt is an illegal character — you have to test the whole base name against the reserved list and rename it when it matches. The standard fix is a safe suffix: CON becomes CON_file, which saves normally and still reads clearly.
Trailing dots, leading spaces, and length
Windows trims a trailing dot or space when it writes a file. Name something notes. and it saves as notes; create a folder called backup and the space quietly vanishes. That sounds harmless until a script that expects the exact name you typed can't find the file, or a sync tool that compares names byte for byte sees a mismatch and re-uploads everything. A leading space is the same kind of bug, just harder to spot. A proper sanitizer strips both leading and trailing dots and spaces so the saved name matches what you intended on every system.
Length is the last constraint. Most filesystems cap a single name component at 255 characters. When a name runs longer, the naive fix — cut off the end — chops the extension too, and archive.tar.gz truncated to 255 characters might lose its .gz and open in the wrong program. The correct approach measures the extension first, then trims only the base name so the total fits while the suffix survives intact.
A worked example
Take a real-world mess of a title that a content export might hand you:
Q3 Review: Sales/Ops "Final"? .pdf
Walk it through the rules one at a time:
- Strip the forbidden characters. The colon, the slash, the two double quotes, and the question mark all go. That leaves
Q3 Review Sales Ops Final .pdf. - Collapse and replace whitespace. Runs of spaces become single underscores so the name has no awkward gaps:
Q3_Review_Sales_Ops_Final_.pdf. - Fix the trailing junk. The space and dot that drifted in front of the extension get cleaned up, and the extension reattaches cleanly:
Q3_Review_Sales_Ops_Final.pdf. - Check the reserved list and length.
Q3_Review_Sales_Ops_Finalis not a reserved name and is well under 255 characters, so nothing else changes.
The final Q3_Review_Sales_Ops_Final.pdf downloads on Windows, sorts cleanly in a file manager, and survives a zip round trip. You can run that exact transformation in the Filename Sanitizer, which does all four steps at once and lets you paste a whole list, one name per line, for a batch.
Why I stopped hand-rolling this
I used to write the strip rules inline every time I built a "download as file" button — a quick regex for the slashes, ship it, move on. It worked until a user exported a report titled with a colon and the download died on Windows with a "file name invalid" dialog that told them nothing. The next time it was a reserved name, which my regex couldn't even see because every character was legal. After the third silent failure I gave up on doing it from memory. Now I run the tricky inputs — CJK text, emoji, reserved names, 300-character titles — through a sanitizer first, confirm exactly what the output should be, and mirror those rules in code with confidence. It is a small list of edge cases, but it is the kind you only remember after one of them has already burned you.
One thing worth keeping: non-ASCII names are safe. Modern Windows, macOS, and Linux all store filenames as Unicode, so 会议纪要.docx or naïve café.pdf is perfectly valid, and a good sanitizer leaves those characters untouched. It removes only the specific illegal punctuation and control bytes, never letters from any language. The single exception is very old systems or some FTP servers that assume single-byte encoding; if you must target those, force lowercase ASCII as well.
Putting it into a workflow
Sanitizing one name is quick. The payoff shows up at scale: a hundred scraped titles, an export feature that runs on every user's input, or a folder you are about to rename in bulk. Clean the names first and the downstream step never chokes on a bad one. If a bulk rename is your actual goal, pair the cleaned list with the Batch File Rename Planner, which turns a parallel list of safe names into the exact shell commands to apply them.
The underlying lesson is the same one that catches everyone once: a filename is a contract with several operating systems at the same time, and the strictest one wins. Sanitize to the strict Windows rule, keep the extension, check the reserved list, and your files stop disappearing on other people's machines.
Made by Toolora · Updated 2026-06-13