Filename Compatibility Pack

The fastest way to find out what your file handling does to a difficult name is to extract this archive on each operating system you support and diff the results. Windows will refuse several outright, macOS will quietly change one of them, and Linux will accept them all.

↓ Download filename-compatibility-pack.zip26 files · 13.0 KB zipped

SHA-256 9c63d68a8b7d98d962a035a78f1bae2adb129a61e9872051ad8accd96984aba0

What is inside

FileFormatSizeExpected result
.hidden-leading-dotTXT142 bytesDirectory listings that filter dotfiles, and extension parsers that see an empty basename.
🦊-emoji-name.txtTXT142 bytesSystems that store names as UTF-16 and count length in code units, or databases on utf8 rather than utf8mb4 - MySQL will reject or truncate this.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txtTXT142 bytesFilesystem limits (255 bytes on ext4, and 255 UTF-16 units on NTFS), plus database columns sized at VARCHAR(100) or VARCHAR(255) that truncate on insert.
ampersand&name.txtTXT142 bytesQuery-string construction and unescaped HTML rendering of the name.
archive.tar.gzTXT142 bytesThe control case for the double-extension test: this one must be accepted.
backslash\name.txtTXT142 bytesCross-platform path handling - Windows treats this as a directory separator, POSIX does not.
CON.txtTXT142 bytesWindows cannot create files named CON, PRN, AUX, NUL, COM1-9 or LPT1-9, even with an extension. Extraction and download on Windows will fail unless the name is sanitised.
dots.in.the.name.txtTXT142 bytesExtension detection that splits on the first dot rather than the last.
double"quote.txtTXT142 bytesContent-Disposition header construction - an unescaped quote terminates the filename parameter early and can inject further header directives.
hash#name.txtTXT142 bytesURL handling - everything after # becomes a fragment and never reaches the server.
invoice‮gnp.txtTXT142 bytesA spoofing vector: the displayed name misrepresents the real extension. Filename display should strip or escape bidi control characters.
nfc-café.txtTXT142 bytesPair with the NFD file. They look identical but differ byte-for-byte, so dedupe and lookup by name must normalise first. macOS stores NFD, Linux stores what it is given.
nfd-café.txtTXT142 bytesThe other half of the normalisation pair.
no-extension-at-allTXT142 bytesType detection that depends on extension rather than content sniffing.
NUL.txtTXT142 bytesSame as CON.txt - writes silently go to the null device on some Windows APIs.
percent%20encoded.txtTXT142 bytesDouble-decoding bugs, where the stored name becomes "percent encoded.txt" after one decode too many.
plus+name.txtTXT142 bytesForm-encoded decoding that turns + into a space.
question?name.txtTXT142 bytesURL handling - everything after ? becomes a query string.
report.pdf.exeTXT142 bytesBlocklists that check only the first extension, and UI that truncates the displayed name and hides the dangerous suffix.
semicolon;name.txtTXT142 bytesContent-Disposition parsing, where semicolon separates parameters.
single'quote.txtTXT142 bytesSQL string building and unquoted shell arguments.
spaces in name.txtTXT142 bytesURL construction that forgets to percent-encode, and shell commands built by string concatenation.
trailing-dot.txt.TXT142 bytesWindows silently strips trailing dots, so this file can collide with trailing-dot.txt on save.
UPPERCASE.TXTTXT142 bytesCase-sensitivity mismatches between a case-insensitive dev machine (macOS, Windows) and a case-sensitive production filesystem (Linux) or object store (S3/R2 are case-sensitive).
файл-кириллица.txtTXT142 bytesAs above, with a different script.
日本語ファイル名.txtTXT142 bytesNon-ASCII names require RFC 5987 filename* encoding in Content-Disposition; the plain filename parameter cannot carry them.
Also in the archive: a README.md repeating this table with full digests, a manifest.json for scripting, and a SHA256SUMS you can check with sha256sum -c. Every file is generated from source, carries no third-party copyright, and is free to redistribute.
Your extractor will probably not give you all 26 files back, and that is the point of the pack. Known behaviour worth expecting rather than reporting as a bug in the archive: - `backslash\name.txt` contains a literal backslash. The ZIP spec uses forward slash as the only path separator, so this is a legal character in a name, but many extractors (including Python's zipfile) treat it as a separator and hand you a directory called `backslash` instead. Both behaviours exist in the wild; neither is a corruption of this archive. - Windows refuses `CON.txt`, `NUL.txt`, `question?name.txt`, `double"quote.txt` and `backslash\name.txt` outright, and silently strips the dot from `trailing-dot.txt.`. - macOS stores filenames decomposed, so `nfc-café.txt` and `nfd-café.txt` may collide into one file on an HFS+ volume and stay separate on APFS. - Case-insensitive file systems collapse `UPPERCASE.TXT` against any lowercase twin. Extract on each platform you support and diff the results against manifest.json.

Questions

Which filenames break on Windows?

Reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) with or without an extension, names containing < > : " / \ | ? *, and names ending in a dot or a space, which Windows silently strips. All of them are in this pack.

Why are there two versions of café.txt?

One is NFC, where é is a single code point, and one is NFD, where it is an e followed by a combining accent. They look identical and differ in bytes. macOS stores filenames decomposed, so a file copied from a Mac can fail to match the same name typed on Windows, which is how you end up with two copies.

How long can a filename be?

Most file systems allow 255 bytes per component, which is fewer than 255 characters as soon as the name is not ASCII. The 200-character name in this pack sits under the limit as characters and over it as UTF-8 bytes in some encodings, which is exactly where truncation bugs live.

Other packs

Upload Torture Test Pack · Encoding and Unicode Pack · Archive and ZIP Security Pack · Document Parser Pack · Image Pipeline Pack · Structured Data Pack · Email Parser Pack