118

I would like to send contents of the current buffer to stdin of external command (like mail).

How do I send a Vim buffer to an external command?

1

2 Answers 2

171

You can use :w !cmd to write the current buffer to the stdin of an external command. From :help :w_c:

                                                        :w_c :write_c
:[range]w[rite] [++opt] !{cmd}
                        Execute {cmd} with [range] lines as standard input
                        (note the space in front of the '!').  {cmd} is
                        executed like with ":!{cmd}", any '!' is replaced with
                        the previous command :!.

A related command is :%!cmd which does the same thing and then replaces the current buffer with the output of the command. So :%!sort would invoke the external sort command to sort the current buffer in place. From :help :range!:

:{range}![!]{filter} [!][arg]                           :range!
                        Filter {range} lines through the external program
                        {filter}.  Vim replaces the optional bangs with the
                        latest given command and appends the optional [arg].
                        Vim saves the output of the filter command in a
                        temporary file and then reads the file into the buffer
                        tempfile.  Vim uses the 'shellredir' option to
                        redirect the filter output to the temporary file.
                        However, if the 'shelltemp' option is off then pipes
                        are used when possible (on Unix).
                        When the 'R' flag is included in 'cpoptions' marks in
                        the filtered lines are deleted, unless the
                        :keepmarks command is used.  Example: 
                                :keepmarks '<,'>!sort
                        When the number of lines after filtering is less than
                        before, marks in the missing lines are deleted anyway.
6
  • 6
    This is useful to format json like: :'<,'>!python -mjson.tool or :%!python -mjson.tool
    – TrinitronX
    Commented Nov 14, 2013 at 23:14
  • 2
    For formatting go, use :%!gofmt without the last %, as that would cause it to use saved version (which may differ from current buffer) Commented May 23, 2017 at 0:36
  • Is there any way for this to replace the current buffer with the command output only on success? If the command returns non-zero, don't replace buffer? Commented May 23, 2017 at 0:37
  • @thomasrutter if the buffer is replaced with an error message instead of the intended output, you can just press u for undo Commented Apr 8, 2019 at 11:57
  • I have looked high and low for docs on :%!my command and have found very little. Where are the docs on this?
    – Aaron Hall
    Commented Mar 24, 2021 at 2:44
2

Here is example how to send the current buffer to external stdin from the command line:

vim -es +"w >> /dev/stdout" -cq! /etc/hosts

It's useful for scripting purposes.

For more command-line tricks, check:

Not the answer you're looking for? Browse other questions tagged or ask your own question.