34

Is it possible to type a bash command inside vi and get the stdout?

I find it often tedious to close and reopen vi just because I want to look something up in the shell.

9 Answers 9

47

Yes, e.g if you want to do ls, try:

:!ls

To spawn a shell, use

:shell

5
  • awesome, how could I live without this?
    – harp
    Sep 11, 2012 at 8:58
  • 4
    In fact something I often do is forget to run vi as root when editing something. This command has saved me from lengthy rewrites more times than I can remember. :w !sudo tee %
    – Mark D
    Sep 11, 2012 at 19:06
  • 1
    i wish there were some way to do this in gnu nano
    – ixtmixilix
    Sep 13, 2012 at 20:56
  • 1
    and then how do you go back to the editor after using :shell?
    – VaTo
    Nov 25, 2016 at 19:59
  • @VaTo : To go back, you can type: exit Mar 7, 2017 at 16:14
14

I tend to use ctrl+z to sleep vi, run what I need to in the shell, then fg to resume vi. Not exactly an answer to your question, but I find it a very fast way to work.

If you do forget that you have vi open in the background (this can happen when you are busy), when you try to log out of the shell using ctrl+d you will be warned that you have background jobs running, and you can either close them, or hit ctrl+d again to log out. Also, if you try to reopen the same file twice, you get a recovery warning, so you can press a to abort,and run fg to go back to vi.

4
  • 1
    This can get sticky if you get caught up in what you're doing on the command line, and forget that you have backgrounded vim.
    – Eliot Ball
    Sep 11, 2012 at 12:30
  • 1
    Yes, it is possible, I have done it myself. For me it is worth it to have shell constancy. I will update my answer to take your comment into account
    – Rqomey
    Sep 11, 2012 at 12:38
  • 1
    I think you would be better off using gnu screen.
    – user606723
    Sep 11, 2012 at 15:03
  • 1
    I use tmux myself... but for speed, and if logged in to a server without tmux or screen, it is handy
    – Rqomey
    Sep 11, 2012 at 15:06
11

Since you mentioned "get the stdout", note that you can do

:r! command

and the output of the command will be added to the file, or

:<range>!command

to have the content of the range filtered through the command [e.g. :1,$!wc]

2
  • :%!command looks pretty useful
    – Eliot Ball
    Sep 11, 2012 at 15:10
  • I use this often for sorting lines [e.g. :.,+20 !sort ]
    – Walter A
    Jan 12, 2015 at 12:54
5

My preferred idiom is

!!command

which is shorthand for

:.!command

which pipes the current line through the command and inserts the output into the file. Most common case for me is to edit the command with vi and run:

!!sh

Or

!<motion>command

such as (for example)

!apsh

to run the whole of the current paragraph through the shell.

1
  • 2
    Note for !} you have to be positioned at the start of the paragraph, try !ap. (I do not know if this is in every vi or only vim)
    – Random832
    Sep 11, 2012 at 16:38
4

By using colon and exclamation point you can run any command in the shell path and shell scripts, keep in mind that the command runs under the user running the vi/vim program, and using it's environment.

:!<command>

Since vi uses the environment that was in effect when it was run, it uses the same path that was in the parent command. Keep in mind that some shells keep a cache of the programs in the path, and vi may not work with this cache (dependent on the shell it uses and it's version), so you may end up running the wrong binary in case you have more than one binary with the same name.

4

You can see the output of a command by typing, for example, :!ls -lh in command mode.

If you'd like to insert the output of the command into the file you're editing, just add an r. For example, :r!which perl.

1

Using ! is obviously the correct answer, but if you're switching back and forth frequently, something like screen or tmux might be helpful, too.

0

I have this in my .vimrc. Found on Stack Overflow a while back:

" Executes the current line in a bash shell; syntactically similar to slimv's ,d feature
:nmap ,,d Y:!<C-R>"<C-H><CR>
0

I would, and do, get round this easily in Linux by opening two terminal command line windows, running vi in one and the other available for other work at the same time.

You must log in to answer this question.

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