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

How do I filter a range of text through an external shell command directly in normal mode?

Answer

!{motion}{cmd}

Explanation

The ! operator in normal mode lets you pipe any motion's text through a shell command and replace it with the output. This is one of Vim's most powerful, lesser-known editing capabilities — turning any external Unix tool into an in-editor transformation.

How it works

  • ! triggers the filter operator, which takes a motion (just like d, y, or c)
  • {motion} defines the range of text to filter (e.g., ip for inner paragraph, G for to end of file, 3j for 3 lines down)
  • {cmd} is the shell command that receives the text on stdin and must write the replacement to stdout
  • The selected lines are replaced with the command's output

The shorthand !!{cmd} filters just the current line (the first ! is the operator, the second is the motion for "current line").

Example

Given the buffer:

banana
apple
cherry

With the cursor on banana, pressing !ip sort<CR> filters the paragraph through sort:

apple
banana
cherry

Or press !!python3 -c "import sys; print(sys.stdin.read().upper(), end='')"<CR> to uppercase just the current line.

Tips

  • !ip sort -u — sort a paragraph and remove duplicate lines
  • !Gpython3 -m json.tool — format JSON from cursor to end of file
  • !ipsort -rn — sort a paragraph numerically in reverse order
  • Works in visual mode too: select lines with V, then press ! to enter filter mode

Next

How do I rename a variable across all its case variants (camelCase, snake_case, SCREAMING_CASE) in one command?