397

Can I search history in bash and run the result?

0

13 Answers 13

565

Type Ctrl R at the command line and start typing the previous command. Once a result appears keep hitting Ctrl R to see other matches. When the command you want appears, simply press Enter

Note that while Ctrl R is the default, if you wanted the command (reverse-search-history) to be bound to Ctrl T you could configure that with the following:

bind '"\C-t": reverse-search-history'

There are a whole host of other readline bindable commands that are available to you as well. Take a look at the bash man page.

Bash has many facilities to search and access interactive command history. The most basic of which is the history builtin. Typing just:

$ history

Will print a list of commands along with a numeric index, like:

$ history
1 clear
2 ls -al
3 vim ~/somefile.txt
4 history
$

You can then execute any of these commands using their numeric index by prefacing the index with a single !, as Mitch pointed out:

$ !1

Will execute the clear command. The history builtin has many features itself, you can see more in the bash and history man pages.

You can also specify relative negative offsets when using the ! designator, so using our history list above, if we wanted to execute vim again, we could do:

$ !-2

Which is basically telling bash to execute the command you ran "two commands ago." To run the previous command in the history list, we can just use !! (which is just shorthand for !-1).

The ! designator doesn't limit you to numerically specifying which command to run. hayalci showed that you can instruct bash to execute a command based on either the text it begins with (using !) or text within the command itself (using !?). Again, using our example history list above, if we wanted to execute clear again, all we need to do is type:

$ !cl

and press Enter. And what about vim? That is as simple as:

$ !?some

The most important point from hayalci's response is the call to the shopt builtin:

$ shopt -s histverify

This will enable history verification so that commands that are matched by the !, !!, and !? designators are not blindly executed, but instead filled in on the command line so you can ensure they will do no evil before executing them. This is even more important when you are executing commands as the root user. This option can be set in your .bashrc startup file so that it is set whenever you log in.

As has already been pointed out, all of this information can be gleaned from the bash man page. For the !, !!, and !? designators, take a look at Section 9.3 History Expansion.

6
  • 50
    +1 I have been Using Linux for over 12 years for all systems. I didn't know that existed. Wish I could +10 how did I miss it??
    – Aiden Bell
    Commented Jul 17, 2009 at 19:27
  • 1
    On many systems, pressing the up-arrow does the same.
    – mas
    Commented Jul 17, 2009 at 20:29
  • If somebody were to consolidate '!', '!!', '!?', 'history | grep', and 'ctrl-r' into a comprehensive answer, I would select it Commented Jul 19, 2009 at 14:09
  • shopt goes in bashrc, not bash_profile (or it won't be enabled for shells that aren't login shells).
    – Tobu
    Commented Jun 29, 2010 at 19:35
  • 2
    Also after pressing CTRL+R you can use CTRL+SHIFT+R multiple times to jump back to the previous command
    – Gal Bracha
    Commented Dec 21, 2015 at 15:55
62

You could also do:

history | grep "stuff"

it would return something like

num stuff

then you can type

!num
1
39

As an alternative to crtl+R, you can search history by typing

!text

This will search the history for the most recent command beginning with 'text'.

But I suggest you put this in your .bashrc to prevent execution of wrong command.

shopt -s histverify

This instructs bash such that, after any history actions (like !!:s/prev_text/after_text), it places the resulting line to the command prompt. Then you can review or edit the command, and press Enter afterwards.

2
  • 6
    Use !?text to re-execute the most recent command containing (as opposed to beginning with) "text".
    – mark4o
    Commented Jul 18, 2009 at 20:36
  • 3
    If somebody were to consolidate '!', '!!', '!?', 'history | grep', and 'ctrl-r' into a comprehensive answer, I would select it. Commented Jul 19, 2009 at 1:21
23

I prefer to use history-search-backward over reverse-search-history. The former lets you type a few characters of the command then press the search key, as opposed to hitting the search key first then typing the search string.

By default on my system, M-p and M-n bind to similar functions but I prefer binding the arrow keys:

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

Excellent writeup, Sean! I'd put this in a comment, but I'm a few reputation points shy. :-)

Another related and useful technique is the ability to run a previous command while changing a word. Say you typoed the directory name, or want to change the file name:

$ echo my name is bob
my name is bob
$ ^bob^jordan
echo my name is jordan
my name is jordan

Notice that the command is expanded, replaced, and output before the command is run, so if the wrong command is run you can see what bash thought it was doing.

14

I have a really great alias, h. It's really just "history | grep", but I filter out previous "h command" entries with the "grep -E -v"

alias h="history | grep -E -v '^ *[0-9]+ *h ' | grep "

used like

h aliases
2003  less .bash_aliases
1
  • 1
    This can also be accomplished by adding the command to HISTIGNORE.
    – tanenbring
    Commented May 15, 2017 at 21:52
8

As navigation through history using Ctrl-r is IMO cumbersome, you may want to consider hh:

https://github.com/dvorka/hstr

which makes navigation much simpler, straightforward and efficient - including running the command:

enter image description here

4
  • How to use it? Which keys to press to see this picture?
    – Nakilon
    Commented Mar 2, 2015 at 13:53
  • 2
    Once you install hh you can either use hh command OR bind it to any keyboard shortcut (typically Ctrl-r) as described in the documentation. Commented Mar 7, 2015 at 6:38
  • it binds to ctrl + r by default now
    – Alleo
    Commented Nov 19, 2017 at 12:42
  • Reason to use hh: "As navigation through history using Ctrl-r is IMO cumbersome", How to use it: "Bind it to Ctrl-r" :- o
    – andrsmllr
    Commented Aug 31, 2022 at 13:31
4

At the bash command prompt, type control-R, then type a few characters of the command you want and bash's readline facility will search through the command history for that command.

After you have started the search, you can type control-R again to jump to the next matching command.

0
3

If you have your shell configured to use vi key bindings (set -o vi or having set editing-mode vi in $HOME/.inputrc), then you search with <Esc>/some-command<Return> and hit n (next) or Shift-n (previous) to cycle through the command line history.

1
  • This one is the closest to vim users. Commented Jun 9, 2017 at 13:23
2

CTRL+R works just fine, like @John1024 suggested, but is somewhat tedious if many of your recent commands are similar and you want a quick way to scan them all. An alternative would be to use history:

$ history | grep keyword
2

I like HSTR, but I can't seem to be able to install it sometimes. So I wrote an alias using fzf which mimics its behavior (hx, for "history execute")

alias hx='eval $(history | sed "s/^ *[0-9]* *//g" | fzf --tac --tiebreak=index --height=10)'
  • history : well, get the history
  • sed : remove the index column from the list (POSIX)
  • fzf : here is the magic, allows you to fuzzy-search the list interactively, move with C-J and C-K, and pick a command with Enter.
  • --height : set the numbers of lines shown.
  • --tac : revert list (more logical for a history)
  • --tiebreak=index : keep the history order when fzf updates the results
1

I have no idea why this is still not mentioned yet. You can set it in your per-user inputrc file like that:

nano ~/.inputrc
# Respect default shortcuts.
$include /etc/inputrc

# Use Shift+Up/Down to search history
"\e[1;2A": history-search-backward
"\e[1;2B": history-search-forward

Super easy, clean, per-user and flexible. Works without any major permissions and will be auto-applied on login.

2
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Feb 21, 2023 at 15:08
  • Or use "\e[1;3A" and "\e[1;3B" for Alt+Up/Down
    – neurino
    Commented Jan 29 at 15:10
0
# USAGE: find.history cd
# filter commands in shell history by a search term and execute the selected command
function find.history {
  eval $(history | grep "$1" | tail | awk '{$1=""}1' | tail -r | peco)
}

You will need to have peco installed.

https://github.com/peco/peco

[$]> brew install peco

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .