238

I have searched, but not found anything on this. I am looking for a functionality in bash, using a terminal.

Way back when, I had a user on a debian system, and a friend set me up with a convenient history search feature (I believe I used tcsh then), where I would type the beginning of a previous command, hit up-arrow, and it would do a search, based on the partial string.

E.g. if my history is:

./script.pl
./script.pl arg1
cat output
cat output | grep yada

And I type ., and press up-arrow, it would show me: ./script.pl arg1. Press it again and it would show ./script.pl, etc.

Very much like it would perform a grep on .bash_history. Is there a way to get this functionality?

TLP
  • 3,341

7 Answers7

321

Create ~/.inputrc and add these lines:

# Respect default shortcuts.
$include /etc/inputrc

arrow up

"\e[A":history-search-backward

arrow down

"\e[B":history-search-forward

Lines starting with # are comments.

I can't remember what is backward and what forward. Experiment with it. Maybe you have to switch backward and forward.

Close and re-open your terminals for the new behaviour to become effective.

Read at the bottom for an explanation of $include /etc/inputrc or what to do if you already have the file ~/.inputrc.


A bit background information:

Bash is using readline to handle the prompt. ~/.inputrc is the configuration file for readline. Note that this will also take effect in other software using the readline library, for example IPython.

Read the bash manual for more information about readline. There you can also find more history related readline commands.

To get the escape codes for the arrow keys you can do the following:

  1. Start cat in a terminal (just cat, no further arguments).
  2. Type keys on keyboard, you will get things like ^[[A for up arrow and ^[[B for down arrow.
  3. Replace ^[ with \e.

For more information about ^[ and \e see here: https://unix.stackexchange.com/a/89817/380515


About the line $include /etc/inputrc:

Readline tries to read ~/.inputrc for configuration. If that file does not exists it will try to read /etc/inputrc. That means if ~/.inputrc exists it will not read /etc/inputrc.

Some distros have prepared some config in /etc/inputrc. If you then create ~/.inputrc you will lose the prepared config. This may or may not be what you want. To still keep the prepared config in /etc/inputrc you can use the line $include /etc/inputrc in your ~/.inputrc.

If you already have the file ~/.inputrc that means you either already know what you are doing. Or you inherited if from the person who set up your system. Or you previously followed a different guide which told you to create the file and forgot about it. Either way you might want to check /etc/inputrc and decide if you want to keep it with the line $include /etc/inputrc.

Lesmana
  • 18,754
54

Create a file named setup_readline.sh with mode 644 in /etc/profile.d/ with following content, login and check you preferred keys:

bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

I think is the best way to do this. Mostly if you using configuration management systems such as chef, puppet, etc

And system config still untouched!

user287613
  • 541
  • 4
  • 2
17

Ctrl + R will give you this sort of functionality. Start typing a partial command and it will come up with old ones which you can navigate with the up and down arrows.

More info here.

Pablo Bianchi
  • 17,371
8

The following solution combines & extends some of the above mentioned approaches: add the following lines to your ~/.bash_aliases file (no need for ~/.inputrc) in order to achieve the following behavior:

  1. move up/down in history (only entries with same prefix) by pressing CTRL+UP and CTRL+DOWN. This can co-exist to the standard functionality of moving up/down in the full history via UP and DOWN alone
  2. jump to next/previous word in a commandline by pressing CTRL+RIGHT and CTRL+LEFT
bind '"\e[1;5A":history-search-backward'
bind '"\e[1;5B":history-search-forward'
bind '"\e[1;5C":forward-word'
bind '"\e[1;5D":backward-word'

Re-login to the shell (or run source ./bash_aliases) in order to apply the changes.

6

To complete lesmana's answer regarding ~/.inputrc that I should create under my Trusty 14.04, verify/add in ~/.bashrc (the first line already exists in my ~/.bashrc):

shopt -s histappend  
PROMPT_COMMAND='history -a'  

It's already explained in French here.

Pablo Bianchi
  • 17,371
bcag2
  • 471
5

There is an alternative similar to what @lesmana mentioned above, but you do not have to create a new .inputrc file.

Instead, if you have sudo permissions, you can enable this in the /etc/inputrc file. In this file are various keyboard settings including the history search feature (for 18.04 at least). The excerpt from /etc/inputrc is:

# alternate mappings for "page up" and "page down" to search the history
# "\e[5~": history-search-backward
# "\e[6~": history-search-forward

Uncomment the bottom two lines using a sudo file editor (e.g., $ sudo vim), and a new terminal session will have the history search feature (for all users). This way, you do not have to worry about creating a ~/.inputrc file, nor will you have to add an $include statement as @Tulio Casagrande mentioned in the comments to preserve your ctrl-arrow inputs.

ascendants
  • 161
  • 1
  • 3
4

Perhaps you may want to try https://github.com/dvorka/hstr which provides simple and multi-line simple filtering of Bash history which as based on a metrics (when, how often and length of commands matters) - you can use arrow keys to easily navigate the history:

enter image description here

It can be easily bound to Ctrl-r and/or Ctrl-s