BASH history – reverse intelligent search

by Ruslan Spivak on November 20, 2010

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.

If you enjoyed this post why not subscribe via email or my RSS feed and get the latest updates immediately. You can also follow me on GitHub or Twitter.

{ 15 comments… read them below or add one }

Taylor Venable November 20, 2010 at 3:57 PM

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.

Reply

Ruslan Spivak November 20, 2010 at 4:08 PM

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

Reply

Harsh November 20, 2010 at 5:30 PM

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_).

Reply

Ruslan Spivak November 20, 2010 at 6:48 PM

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 :)

Reply

beroal November 23, 2010 at 4:59 AM

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.

Reply

Ruslan Spivak November 24, 2010 at 2:34 PM

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.

Reply

Juan Pablo Almonacid February 13, 2013 at 1:22 PM

Thanks for your tips about the Ctrl-S keybinding!

Reply

1cc May 24, 2013 at 8:01 AM

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).

Reply

Pierre B. April 13, 2012 at 10:05 AM

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.

Reply

Sys September 18, 2012 at 5:57 AM

> 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.

Reply

/bin October 3, 2012 at 8:08 PM

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.

Reply

Adam June 17, 2013 at 8:00 AM

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.

Reply

thinf August 14, 2013 at 1:55 AM

Thanks! I guess I ow you a beer…

Reply

Martin Gafner February 18, 2014 at 4:53 AM

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.

Reply

Martin July 14, 2014 at 11:27 PM

Perhaps you could consider BASH history suggest box https://github.com/dvorka/hstr that greatly simplifies navigation through the history and its management.

Reply

Speak your mind

{ 3 trackbacks }

Previous post:

Next post: