vimtricks.wiki Concise Vim tricks, one at a time.

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 to system() 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'))

Next

How do I find all files matching a pattern across all directories in Vim's runtimepath?