I know that, while in Vim (and Vi, too, I think), if I want to temporarily access the shell I can do one of several things:

  • Use :sh (a.k.a. :shell), then log out from the shell to return to Vim
  • Use :sus (a.k.a. :suspend, :st, or :stop), then use fg to return to Vim
  • Use :! <command> to pass commands through Vim to the shell
  • Use :mksession <filename> to save a session, quit Vim, then restore the session with :source <filename> after returning to Vim (admittedly this is probably too cumbersome for most "temporary" shell access needs)
  • Use windowing software such as screen, tmux, etc.

My question is, what are the technical and practical differences of the first two options—using :sh vs. using :sus? In the Vim help pages, it looks like the only difference is that with :sus, you either automatically write out the buffer (if 'autowrite' is set) or you risk losing your edited buffers if you never return to Vim, whereas with :sh you have no choice but to return to your Vim session when you exit the shell.

Are there any other differences, either technically (such as memory and processor use) or productivity-related reasons why a Vim user might choose one method over the other in different situations?

  • I left one other difference out that is listed in Vim help: in certain environments, one cannot paste text that was yanked from a stopped/suspended Vim, whereas you apparently don't lose that ability when starting a subshell. – Andy Mo Nov 29 '12 at 13:59

To me, the biggest difference between :suspend and :shell is that with the former, you return to the original shell, whereas the latter starts a new subshell. This means that (non-exported) environment variables are available in the former, but not in the latter. From a performance perspective, depending on your customization (e.g. in ~/.bashrc), the startup of a new shell might introduce a noticeable delay.

In general, there is no right or wrong answer to your question. Vim (as it's a derivative of the Unix philosophy) allows you to find and pick your own style. Personally, I always do major edits in GVIM and only use console Vim for short, tactical edits (e.g. a quick change in config files). I also always have multiple terminals open, so I rather switch to another terminal with Alt + Tab than shell out from Vim.

  • 1
    Also changes to the environment (:let $VARIABLE='blah') or current directory (:cd some/dir) made from within vim would be reflected in a shell started using :shell, but would not be in the parent shell accessed via :suspend. – qqx Nov 28 '12 at 16:55

Using :sh creates a new process — a child process of the vi process — and runs a new shell.  :sus puts the editor into a suspended state and allows the parent process (typically, your login shell, or the primary shell in the window) to take control back.  So :sh uses marginally more resources.  But the bigger difference is that if you run :sh and then do cd (change directory), set a shell variable / environment variable, change a process limit (ulimit), or anything else that affects the shell directly, then those effect(s) will disappear when you return to the editor (by exiting the shell).  Conversely, if you go back to your primary shell, then the effects will still be there when you exit from the editor.

And Ingo’s answer about (non-exported) shell variables in the parent shell not being available in the subshell is correct also.

Oh, another thing: :sh will probably give you an instance of the shell named by $SHELL.  If your parent shell is something different, then that will, obviously, be another difference.


Oh, something else I just thought of: depending on what shell you are using (bash, C shell, zsh, etc.) and what settings you have in effect, a subshell probably won’t have access to the primary shell’s command history (e.g., !-2 or ).  As a trivial corollary, which you’ve probably already observed, the fg that you must type to get back into the editor after a :sus does get added to the primary shell’s command history.  I often save and exit from the editor, and then immediately say to myself, “Oh! I forgot to change «Humpty» to «Dumpty».”, and type !!Enter to get back into the editor, only to be caught off guard by the fact that the !! brings up the fg command.  In bash, you can prevent this by setting HISTIGNORE to fg (or adding fg, delimited by a :, to your existing HISTIGNORE list, if any).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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