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

How do I send a range of lines as stdin to a shell command without modifying the buffer?

Answer

:[range]w !{cmd}

Explanation

The :[range]w !{cmd} command writes a range of lines to the standard input of a shell command, leaving the buffer completely unchanged. This is subtly different from :[range]!{cmd}, which replaces the lines with the command's output — a critical distinction that experienced Vim users often mix up.

How it works

  • :[range] — any line range: 1,5, '<,'> (visual selection), % (whole buffer)
  • w ! — the space before ! is significant: it means write to stdin rather than filter and replace
  • {cmd} — any shell command that reads from stdin

Example

To count lines in a visual selection without leaving Vim:

:'<,'>w !wc -l

To send selected lines to a clipboard tool on Linux:

:'<,'>w !xclip -selection clipboard

To validate selected JSON:

:'<,'>w !python3 -m json.tool

The buffer remains untouched in all cases.

Tips

  • Contrast with :'<,'>!cmd (no w) — that replaces the selection with the command output
  • Use %w !cmd to send the whole buffer as stdin
  • Output from the command appears in a message area but is not inserted into the buffer; use :[range]r !cmd if you want the output inserted
  • This is ideal for linting/validating a range, sending to external tools, or quick ad-hoc calculations

Next

What is the difference between the inner word (iw) and inner WORD (iW) text objects in Vim?