Robust File Naming
File names that survive contact with reality must work across every layer that touches them — filesystems, sync tools, shells, web servers, markup parsers, and personal knowledge tools — and each layer reserves its own characters. A name that is legal on ext4 may be un-cloneable on Windows, un-referencable in Markdown, or an injection vector in a shell loop. Robust naming is the intersection of all the reserved sets.
The avoid-list, by layer
- Non-ASCII — Unicode handling across tools/filesystems (NFC vs. NFD on macOS vs. Linux) is still too inconsistent to stake a filename on.
- Control characters — including tabs and newlines (legal on Unix, catastrophic in scripts).
- Exotic whitespace — plain spaces are now fine almost everywhere; non-breaking spaces and their kin are not.
- Filesystem-reserved:
/ \ : * ? " < > |— the union of NTFS, HFS+/APFS, and ext4 restrictions (Windows is the strictest common denominator; also avoid DOS device names likeCON,NUL,aux). - HTML/XML-reserved:
& < > ' "— these surface as bugs in the weirdest places (exported HTML indexes, XML manifests). - URL-reserved:
! " # $ % & ' ( ) * + , / : ; = ? @ [ ]— anything that will be percent-encoded is a future broken link. - Tool-specific reserved — e.g. Obsidian/wiki links:
# ^ [ ] |. - Shell metacharacters:
` ~ ! # $ & * { } | \ /— legal in names, but a standing invitation to command-injection and globbing accidents (see bash-wildcard-abuse).
The practical rule
Stay inside [a-zA-Z0-9 , . _ -] plus plain spaces — or go stricter (lowercase-hyphen, like this wiki’s own convention) when names double as identifiers. Audit an existing tree for violations with:
find -E . -not -regex "^.*/[ a-zA-Z0-9',_.-]+$" -not -path "."(GNU find: drop -E and use -regextype posix-extended.)
Sources
Related
- unix-permissions — names are only half of portable file hygiene
- bash-wildcard-abuse — why shell-meaningful filenames are a security issue, not just an annoyance
- regex-metacharacters — the audit regex above as a worked example