Command Line History Searching
While using the Unix command line, I often want to find a command I previously typed, e.g. the last "ssh" command I typed. Using the up and down arrows or "Ctrl-p" and "Ctrl-n" to go through each line is often very tedious because there's lots of other cruft in the history since the last time I typed "ssh". tcsh
, the first "real" Unix shell I used, has a nice history search mechanism: type "ssh" then "ESC-p". It'll go back through your history and find the last time you typed "ssh". Hit "ESC-p" again , and it'll go to the one before that. Hit "ESC-n" and it'll go forward to the next one. Thus using "ESC-p" and "ESC-n" allows you to interactively go up and down through your history, like the up and down arrow keys, but only matching what you have typed so far. Also, "ESC" is an alias for the "META" key, which is mapped to "ALT" in most GUI terminal programs. Thus, you can just use "ALT-p" and "ALT-n".
My current shell is zsh
, which I switched to maybe four years ago. By default, zsh
doesn't have key bindings for "ESC-p" and "ESC-n". Since this was one of my favorite tcsh
features, figuring out how to do this was a requirement for me to stick with zsh
. Luckily, it has functions to do this, the key bindings just need to be setup. Here's the snippet from my ~/.zshrc
:
# "^[" is what the "ESC" key looks like to zsh bindkey "^[p" history-beginning-search-backward bindkey "^[n" history-beginning-search-forward
Now, I've had my zsh
setup like this for a very long time. But occasionally I'm forced to use bash
or, more likely, some other program which uses GNU readline
. The default GNU readline
bindings for "ESC-p" or "ESC-n" do not behave like tcsh
, so I lose one of my favorite features. I've tried using "Ctrl-r" to interactively search backward through history, however I find it's behavior annoying for a few reasons. First, it matches anywhere in the the command string, not just the start of a command. I find this matches many history commands that are irrelevant. Second, it only starts matching after you type "Ctrl-r". Finally, I always seem to hit "Ctrl-r" one too many times, and there doesn't seem to be a way to search forward in history. And again, luckily
readline
has functions to do history the way I like, the key bindings just need to be setup. readline
looks in ~/.inputrc
for customization, so I put these lines in there to get what I want:
# "\e" is what the "ESC" key looks like to readline "\ep": history-search-backward "\en": history-search-forward
Now, I can finally be (somewhat) happy in bash
or any readline
application.