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

How do I filter the entire buffer (or a range of lines) through an external shell command?

Answer

:%!

Explanation

The ! operator pipes text through a shell command, replacing the selected lines with the command's output. Prefixing with % applies it to the entire buffer. This turns Vim into an integration point for any Unix tool — sorting, formatting, transforming — without leaving the editor.

How it works

  • % — the range meaning "all lines"
  • !{cmd} — pass the range to {cmd} via stdin, replace it with stdout

So :%!sort sends all lines to sort and replaces the buffer with the sorted output.

Example

Format a JSON file in-place using jq:

:%!jq .

Before:

{"name":"alice","age":30}

After:

{
  "name": "alice",
  "age": 30
}

Other useful patterns:

:%!sort -u          " sort and deduplicate lines
:%!column -t        " align columns
:5,20!indent        " run indent formatter on lines 5–20
:.!date             " replace current line with today's date

Tips

  • Use a visual selection then press ! to filter only the selected lines — Vim auto-fills :'<,'>
  • If the command fails or produces no output, Vim restores the original lines
  • :.!{cmd} filters only the current line; :1,.!{cmd} filters from line 1 to the cursor
  • Combine with undo (u) if the result is not what you expected

Next

How do I run text I've yanked or typed as a Vim macro without recording it first?