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

How do I safely pass a Vim variable or the word under the cursor as an argument to a shell command?

Answer

shellescape({expr})

Explanation

The shellescape() function wraps a string in shell-safe quoting, escaping any special characters so it can be embedded in a shell command constructed with :execute '!' . ... or :call system(). Without it, words containing spaces, quotes, dollar signs, or other shell metacharacters silently break the command — or worse, enable unintended execution.

How it works

  • shellescape({string}) returns the string wrapped in single quotes (on Unix/macOS) with internal single quotes properly escaped
  • An optional second argument (1) adds extra backslash escaping for use in :! commands, which process backslashes before the shell does
  • Works in tandem with expand(), getreg(), and similar functions that yield user-controlled strings

Example

Grep for the exact word under the cursor across all files — safely:

:execute '!grep -rn ' . shellescape(expand('<cword>')) . ' .'

Without shellescape(), a word like it's or foo bar would corrupt the command. Compare:

" UNSAFE — breaks on spaces, quotes, special chars:
:execute '!grep ' . expand('<cword>') . ' ' . expand('%')

" SAFE — handles any content correctly:
:execute '!grep ' . shellescape(expand('<cword>')) . ' ' . shellescape(expand('%'))

Using with system() to capture output into a variable:

let l:result = system('wc -l ' . shellescape(expand('%:p')))
echo l:result

Tips

  • Use shellescape(s, 1) (the 1 flag) only for :! commands; for system() the plain form is correct
  • fnameescape() is the Vim-side counterpart — use it for Ex commands like :edit and :read, not for shell commands
  • Always escape every variable that might contain user input or file paths, even ones that look safe during development
  • For building complex shell pipelines, consider assembling the whole command as a string first and echoing it before executing, to verify quoting looks correct

Next

How do I encode and decode JSON data in Vimscript for configuration and plugin development?