Ruslan's Blog Ruslan's Blog
Search
BASH history – reverse intelligent search

When I tell developers about Ctrl-R in BASH usually I get responses literally ranging from “Are you @#$%^&* kidding me? Who doesn’t know it?” to “Thank you. Thank you. Thank you. I owe you a beer”. Well, I made it up about the beer but I figure that people usually imply it :)

This BASH keybinding is so important for developer’s productivity that it’s well worth repeating it over and over again.

OK, here we go. If you know roughly the contents of the command, but can’t recall where it is in a BASH history list and don’t want to go through that list by hand, then just press Ctrl-R to do a reverse intelligent search.

As you start typing the search goes back in reverse order to the first command that matches the letters you’ve typed. By typing more successive letters you make the match more and more specific.

Once you’ve found the command you have several options:

  1. Run it verbatim – just press Enter
  2. Edit it before running – you can use arrow keys or different key bindings to navigate to the point you want to edit
  3. Cycle through other commands that match the letters you’ve typed – press Ctrl-R successively
  4. Quit the search and back to the command line empty-handed – press Ctrl-G

Update:

Added a fourth option that I forgot to mention. Thanks to commenter Taylor for reminding me about it.

arrow14 Responses

  1. 44 mos, 3 wks ago

    Actually I think the term “i-search” means “incremental search” as in Emacs, since it searches incrementally as you type what you’re looking for. Definitely a time-saver, and just like in Emacs if you ever go back too far in your history looking for matches, you can type C-g to get out of it and reset your position in the command history to where you were before you started searching.

  2. Ruslan Spivak
    44 mos, 3 wks ago

    Hi Taylor,

    You’re absolutely right – in Emacs parlance it’s called incremental search. I called it that way in contrast to a dumb search with arrow keys :)
    And thanks for reminding about keyboard quit key binding C-g

  3. 44 mos, 3 wks ago

    In BASH, whe{r|n}ever I can, I always have my up/down buttons mapped to history-search-backward and history-search-forward (via .inputrc).

    I find this alternative to history searching better (but of course, I don’t use emacs _yet_).

  4. Ruslan Spivak
    44 mos, 3 wks ago

    This is a viable alternative with an additional benefit of allowing search in both directions.

    Why I personally prefer Ctrl-R though:
    1. The power of default – you can go to someone else’s box and use the same binding in their BASH
    2. Being Emacs junkie this is a reasonable choice for me :)

  5. 44 mos, 3 wks ago

    That is so true. I have additional tips:
    * Use “history” and “grep” commands for complex searches.
    * Increase the history memory by setting environment variables
    {{{
    HISTSIZE=10000
    HISTCONTROL=ignoredups
    }}}
    * Add “#” at the beginning of the command or use “history add” to save a command without running.

    I would do anything to know how I can:
    * Obtain a command with a specific number to the edit buffer.
    * Go backwards when searching with Ctrl+R.

  6. Ruslan Spivak
    44 mos, 3 wks ago

    Hey beroal,

    Thanks for the tips – especially liked the one with a pound sign #, never heard of it before.

    This might be what you need:
    - to edit a command with a specific number: $ fc 127
    where 127 is the command number
    - Ctrl-R + go backwards. The method that works for me is to un-shadow BASH Ctrl-S keybinding (terminal shadows it with its own interpretation of Ctrl-S which is to freeze terminal):
    $ stty stop ^X
    That will rebind freezing terminal to Ctrl-X and now Ctrl-S should work as incremental search forward, so once you press Ctrl-R you can go backwards by simply pressing Ctrl-S
    Hope that helps.

  7. 27 mos, 3 wks ago

    Thank you ruslan for the Ctrl-S tips, i’ve been wondering for quiet some time how it was possible to go back to normal direction when inside an ‘i-search’ context, i decide just 5 min ago to finally search for a solution, and bang here i found it there.

    Thanks.

  8. Sys
    22 mos, 2 wks ago

    > Quit the search and back to the command line empty-handed – press Ctrl-G
    You can use Ctrl-C. It’s easier to remember, as you already remember it.

  9. /bin
    22 mos ago

    I recommend to use Ctrl-G because it’s a clean way to terminate the search back function. Ctrl-C is more or an interrupt to the open process.

  10. Juan Pablo Almonacid
    17 mos, 3 wks ago

    Thanks for your tips about the Ctrl-S keybinding!

  11. 1cc
    14 mos, 1 wk ago

    To obtain a command with a specific number to the edit buffer, you can put these two functions and the binding in your .bashrc file.

    function hget() {
    history | egrep “^ +$1 ” | awk “{sub(/^ +$1 /,\”\”);print}” > /tmp/READLINE_BUFFER

    _rlyank() {
    READLINE_LINE=”${READLINE_LINE:0:$READLINE_POINT}$(cat /tmp/READLINE_BUFFER)${READLINE_LINE:$READLINE_POINT}”
    }

    bind -m emacs -x ‘”\ey”: _rlyank’

    This will allow you to use the hget command followed by a command number (e.g. hget 1 to get the first history entry), after which you can yank the command to your edit buffer with alt-y (or if not alt, then whatever your meta key is).

  12. Adam
    13 mos, 2 wks ago

    beroal asked how to “Obtain a command with a specific number to the edit buffer”
    You can retrieve an old command without running it to the front of the history with !NUM:p where NUM is the history index. Then use up-arrow to get it back.

  13. thinf
    11 mos, 2 wks ago

    Thanks! I guess I ow you a beer…

  14. 5 mos, 1 wk ago

    Just write in your bash:

    # set -o vi

    and now you press escape and may use all vi commands to search (with /) and cycle (with j and k) through your bash history.

Leave A Comment