13

I want to find the alternative to ctrl+R to search history in bash. I can enable vi mode in bash but I cannot make it search. When I do /search or ?search nothing happens. Is there something more I should press? I tried press enter and then this happens:

$ set -o vi
$ ls|grep f
$ /gr
-bash: /gr: No such file or directory
$
3
  • 2
    Is <C-r> really not working for you in vi-mode for readline? It works fine for me with the latest version of bash.
    – D. Ben Knoble
    May 31, 2018 at 0:57
  • @D.BenKnoble Yes it is, but I think <C-r> is emacs mode and I want to learn vi mode. May 31, 2018 at 1:38
  • 1
    <C-r> is just recursive search; not sure it has anything to do with emacs vs vi, especially as it might be a bash-specific extension (my memory is fuzzy on that detail). Im not discouraging you from using /, just that each has its (different) uses.
    – D. Ben Knoble
    May 31, 2018 at 1:42

2 Answers 2

26
+50

There certainly is Vim style searching in bash/readline. In fact, your command line is essentially a scaled down version of the Vim editor with a significant number of Normal mode commands available to you. More on that in a sec but first Search. The key piece of information you need is that as you stare at that blinking cursor on your command line you are in the equivalent of Vim's Insert mode. So how do we get to Normal mode? By hitting Esc, of course.

From there hit /, enter a search term and hit Enter. Now you can use n and N to move back and forth through the results. (You'll effectively be searching backwards by default with n...searching forwards from the start wouldn't give any results since there's no history in the future!) To execute the current result as a command hit Enter again.

Don't forget that you're in Normal mode, though, so if you don't find what you're looking for and want to get back to entering text in Insert mode do what you usually do in Vim. Hitting i, for example, will do it. Or you can use Vim command C which will remove any text after the cursor and enter Insert mode, which is handy. (You can precede that with 0 if you moved the cursor past the first column.) Or use A, a, R, s, s, I, Ctrl-C...you get the picture.

Besides the various commands that enter Insert mode you get can navigate with b, B, e, E, w, W, 0, $, etc. Yank/delete/put are there, too, and you can use them in them in action+navigation commands like yB, c2e, d$, etc.1 Finally, undo works as well! Go ahead and try some other stuff yourself.

Oh, and if you get a bit lost or, as happens to me once in a while, some funkiness with line wrapping scrambles your c/l you can drop the pretense and hit v. This pulls your command line's contents into an actual instance of Vim so you can edit with a Fully Armed and Operational Text Editor. Once done, :wq to submit what you have to the shell for execution.

1Alas, the operator+motion commands (caw, dis, yap, etc.) aren't supported. But @EdNeville's comment below has a link to some readline settings that will add seemingly every op-motion command there is as well as a number of others. You can really round out your command-line based Vim experience by adding them to your .inputrc file.


Additional Info: You are not restricted to using just what set -o vi or set -o emacs gives you. You can use any of the available readline commands. I believe Ctrl-R should be available even in Vim mode but if not you can try putting this in your ~/.inputrc ...

set editing-mode vi
"\C-r": reverse-search-history
"\C-s": forward-search-history

Better yet, you can add some otherwise unavailable commands like

"\C-o": operate-and-get-next

With this, once you have selected a command from history (e.g. via Vim search) hit Ctrl-O instead of Enter and Bash will run the command and insert the next command from history, ready to run.

See Readline Command Names section in the Bash manpage for complete list.

(You can also configure these from the command line with the bind command but I'm already getting too far afield here.)

9
  • 2
    Nice. A learning moment. May 31, 2018 at 0:51
  • 1
    @niklas, this is your answer May 31, 2018 at 0:51
  • @glennjackman Wow! Cool. I just had to press Esc first. Thanks for this. May 31, 2018 at 1:43
  • 2
    @NiklasRosencrantz Yep, I understood. We try to write answers that are generally useful rather than solely focused on the questioner so I added the extra information about mixing commands from different modes.
    – B Layer
    May 31, 2018 at 2:12
  • 1
    You can also add things like ciw if you modify .inputrc: usenix.org.uk/content/bash.html#input
    – Ed Neville
    Mar 5, 2020 at 18:21
3

what @B-Layer mentioned works pretty well in bash and similarly in zsh.

Since you are already using VIM, and if you are using neovim or vim8, you can also try :terminal, which will open the default terminal in vim.

Then you can use vim command to navigate the output of the termminal, as well as navigate the history of the terminal commands.

Ref.

  1. http://vimcasts.org/episodes/neovim-terminal/
  2. https://neovim.io/doc/user/nvim_terminal_emulator.html
  3. https://github.com/vim/vim/blob/master/runtime/doc/terminal.txt

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.