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

How do I filter buffer contents through an external shell command?

Answer

:%!{cmd}

Explanation

The :%!{cmd} command pipes the entire buffer through an external shell command and replaces the buffer contents with the command's output. This turns Vim into a powerful text processing hub where you can leverage any Unix tool — sort, awk, sed, python, jq, and more — without leaving your editor.

How it works

  • % is the range specifying the entire file (you can also use a visual selection or a line range like :.! for the current line)
  • ! is the filter operator — it sends the specified range to an external command's stdin
  • {cmd} is any shell command that reads from stdin and writes to stdout
  • The output of the command replaces the original range in the buffer

Example

Given unsorted text:

banana
apple
cherry
apple
banana

Running :%!sort -u replaces the buffer with sorted, deduplicated output:

apple
banana
cherry

Format a JSON blob with :%!jq . or reformat Python with :%!black -.

Tips

  • Use :.!date to replace the current line with the output of the date command
  • Use :'<,'>!sort to sort only the visually selected lines
  • Use !{motion}{cmd} from normal mode — e.g., !ip then sort to filter the current paragraph through sort
  • :%!column -t is a quick way to align columns in whitespace-delimited data
  • Undo with u if the result isn't what you expected — the entire filter operation is one undo step
  • Use :%!nl -ba to add line numbers to every line in the file
  • Pair with :%!awk or :%!sed for complex transformations that would be tedious with Vim's built-in commands

Next

How do I edit multiple lines at once using multiple cursors in Vim?