Pipe output of shell command (!) into a new buffer in Vim

35

15

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

Richie Marquez

Posted 2010-06-29T05:32:42.860

Reputation: 1 393

1http://stackoverflow.com/questions/3826003/how-do-i-dump-output-of-an-external-command-to-a-new-buffer-in-vim – Ciro Santilli 新疆改造中心法轮功六四事件 – 2015-06-13T07:25:36.370

Answers

27

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

garyjohn

Posted 2010-06-29T05:32:42.860

Reputation: 29 085

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. – Richie Marquez – 2010-06-29T06:44:36.403

@Richard Marquez: i updated this answer. the new tab is now opened with the "old" filename, thus you could call :!echo % – akira – 2010-06-29T08:24:14.663

But not :r!echo without altering the buffer. – Luc Hermitte – 2010-06-29T09:27:48.283

@Luc Hermitte: right, i ll rollback. – akira – 2010-06-29T11:04:52.413

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 #". – Richie Marquez – 2010-06-29T14:22:46.147

1Might 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>. – Richie Marquez – 2010-06-29T18:15:20.680

18

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.

overthink

Posted 2010-06-29T05:32:42.860

Reputation: 281

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 – 2017-07-20T19:28:51.747

4

:tabnew | enew | r ! <your shell cmd>

works for me.

justrajdeep

Posted 2010-06-29T05:32:42.860

Reputation: 141

2

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>

Luc Hermitte

Posted 2010-06-29T05:32:42.860

Reputation: 1 575

see the other answer, you can do it without storing the name in a variable. but good answer anyway. – akira – 2010-06-29T11:12:41.927

Indeed. I wasn't sure '#' will give the expected result in that case -- as I never use tabs – Luc Hermitte – 2010-06-29T12:42:28.807