How do I safely use a filename containing special characters in a Vim Ex command?
Answer
fnameescape(filename)
Explanation
When building Vim Ex commands dynamically, filenames with spaces, |, %, #, [, or other special characters will be misinterpreted — the space looks like an argument separator, | chains commands, % expands to the current file, and so on. fnameescape() prepends backslashes before any such characters, making the filename safe to embed in Ex commands like :edit, :write, :read, or :find.
How it works
fnameescape(string)returns the string with special Ex characters backslash-escaped- Characters escaped include: space,
\t,|,%,#,",[,{,!,;, and others - Use
shellescape()for shell commands — it uses different quoting rules
Example
Open a file with spaces and special characters in a mapping:
let fname = '/home/user/my notes (draft) #2.txt'
execute 'edit ' . fnameescape(fname)
Without fnameescape(), the spaces and # would break the :edit call. With it, the command becomes:
edit /home/user/my\ notes\ (draft)\ \#2.txt
Another common pattern — open a related file in the same directory:
execute 'split ' . fnameescape(expand('%:h') . '/related.txt')
Tips
fnameescape()is for Vim Ex commands;shellescape()is for shell commands passed tosystem()or:!- When using filename modifiers directly (e.g.,
%:h), Vim expands them automatically —fnameescape()is only needed for dynamic strings in Vimscript - For forward slashes in substitution replacements, use
escape(fname, '/')instead - Combine with
expand()safely:fnameescape(expand('~/.vim/init.vim'))