61

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

40

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
7
  • 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. Commented 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
    Commented Jun 29, 2010 at 8:24
  • But not :r!echo without altering the buffer. Commented 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 #". Commented 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>. Commented Jun 29, 2010 at 18:15
30

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
    Commented Jul 20, 2017 at 19:28
  • can this be done without a leading newline?
    – CervEd
    Commented Feb 2, 2023 at 9:28
  • I figured it out :new | 0r !ls ^@ $,$d where ^@ is <CR> entered using CTRL-V CRTL-J
    – CervEd
    Commented Feb 2, 2023 at 12:55
5
:tabnew | enew | r ! <your shell cmd>

works for me.

4

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
    Commented Jun 29, 2010 at 11:12
  • Indeed. I wasn't sure '#' will give the expected result in that case -- as I never use tabs Commented 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .