55

How can I pipe the output of a shell command into a new buffer in Vim? The following obviously wouldn't work, but you can see what I'm getting at:

:!echo % | :newtab
1

5 Answers 5

37

You can't pipe the output of a shell command into a command that creates a new buffer, but you can create a new buffer and read the output of a shell command into that buffer with one entry on Vim's command line. A working version of your example would be

:tabnew | r !echo <c-r>=bufname("#")<cr>

Note that the pipe symbol in this case is a separator between Vim ex commands, not the shell's pipe. See also

:help :tabnew
:help :r!
:help :bar
6
  • That's almost exactly what I need, just the other way around so that I can access the filename of the current buffer. Note: updated the question to hopefully clarify the desired end result. Jun 29, 2010 at 6:44
  • @Richard Marquez: i updated this answer. the new tab is now opened with the "old" filename, thus you could call :!echo %
    – akira
    Jun 29, 2010 at 8:24
  • But not :r!echo without altering the buffer. Jun 29, 2010 at 9:27
  • 2
    @garyjohn, akira: thanks for the help. The "<c-r>=..." part made Vim spew errors, but I was able to get it working with ":tabnew | r !echo #". Jun 29, 2010 at 14:22
  • 1
    Might also be useful to note that if you want to map this to a key in your .vimrc, you'll need to replace the | character with <bar>. Jun 29, 2010 at 18:15
25

Here's what I do. It's alluded to in comments in the above answers.

:new | r ! <cmd>
:new | r ! <cmd> #   (# is replaced with filename)

Example 1: Find all text files in /tmp

:new | r ! find /tmp -name '*.txt'

Example 2: You're editing file foo.txt and you want to run ls -la foo.txt and get the output in a buffer:

:new | r ! ls -la #

The # is replaced with the filename of the original buffer you're editing. This is particularly useful for ad-hoc source control commands e.g.

:new | r ! hg annotate -un #

:new creates a horizontal split, use :vnew if you want a vertical split instead and :tabnew for a new tab.

3
  • Are you able to answer this question here as well? it is about trying to use the current buffer with % for the next buffer but E499.
    – hhh
    Jul 20, 2017 at 19:28
  • can this be done without a leading newline?
    – CervEd
    Feb 2 at 9:28
  • I figured it out :new | 0r !ls ^@ $,$d where ^@ is <CR> entered using CTRL-V CRTL-J
    – CervEd
    Feb 2 at 12:55
5
:tabnew | enew | r ! <your shell cmd>

works for me.

3

If you really require to store the result in a new buffer, but require info from the old current buffer, then you can either use system():

:let res = system('echo '.expand('%'))
:tabnew
:put=res

or store the current buffer name for later:

:let bn = expand('%')
:tabnew | :r!echo <c-r>=bn<cr>
2
  • see the other answer, you can do it without storing the name in a variable. but good answer anyway.
    – akira
    Jun 29, 2010 at 11:12
  • Indeed. I wasn't sure '#' will give the expected result in that case -- as I never use tabs Jun 29, 2010 at 12:42
0

@Ciro Santilli linked the answer https://stackoverflow.com/a/3826018/9306292

:enew | .! <command>

If you want to keep your configuration simple, use one of those:

<C-w>v / <C-w>s / yourtabkeybinding, ie <C-w>t

and then

:%!command

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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