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
:.!dateto replace the current line with the output of thedatecommand - Use
:'<,'>!sortto sort only the visually selected lines - Use
!{motion}{cmd}from normal mode — e.g.,!ipthensortto filter the current paragraph throughsort :%!column -tis a quick way to align columns in whitespace-delimited data- Undo with
uif the result isn't what you expected — the entire filter operation is one undo step - Use
:%!nl -bato add line numbers to every line in the file - Pair with
:%!awkor:%!sedfor complex transformations that would be tedious with Vim's built-in commands