8

How can I grab a command from history by number to my command line without executing it?

This immediately executes command number 555 which I'm not looking for:
$ history 10
$ !555

This opens the command up in an editor, which is overkill most of the time:
$ history 10
$ fc 555

This is an example of what I'm looking for:
$ history 10
$ #555
$ [command 555 from history listing now sitting here on my command line ready to edit or execute]

Thank you!

3
  • history, then use mouse to highlight , then ctrl-shift-c to copy to clipboard , then ctrl-shift-v to paste it to command line (of course this is a manual process)
    – pierrely
    Commented Mar 27, 2021 at 5:29
  • This looks like a xyproblem: you ask for a specific method, and thus may miss a faster and more appropriate solution to your need. Always specify the overall need you're trying to fulfill, instead of (or at least in addition to) asking for some specific steps. I believe your need is : "find a previously entered command, edit it, and execute it." ? If so, I added an answer with a vastly more efficient method to achieve this (if I guessed correctly?) Commented Mar 29, 2021 at 10:24
  • I fixed my answer (for some reason I said "ctrl-f something", where it is in fact "ctrl-r something" (which I use many times a day without thinking...) Commented Mar 31, 2021 at 8:23

5 Answers 5

15
shopt -s histverify

If the histverify shell option is enabled, and Readline is being used, history substitutions are not immediately passed to the shell parser. Instead, the expanded line is reloaded into the Readline editing buffer for further modification.

3
  • Every response was helpful. Thank you everybody. This answer solves the intent of what I'm after, the ability to very simply retrieve a specific history command to the command line without executing it. I added this to my .bashrc file: shopt -s histverify. Thank you very much everyone! I really appreciate the support in this community. When I get into Linux more, I might try my hand at writing a command that accomplishes histverify with #555 so that I can still use !555 when I know I just want to execute that specific command from history. Thanks again! Commented Mar 26, 2021 at 19:38
  • histverify is often used in conjunction with histreedit it gives the opportunity to re-edit a failed history substitution, e.g., !nonexistant
    – user986805
    Commented Mar 26, 2021 at 19:48
  • for the needed stated by @KevinBerry : ctrl-r something is imo much faster: no need to do a "history" to find out which number the interresting line is at, the shell does the search for you and present it in edit mode. another ctrl-r looks further back for the same "something". But this answer is still usefull for other history substitutions (ex: !!, or other variants shown in gnu.org/software/bash/manual/html_node/Event-Designators.html ) Commented Mar 31, 2021 at 8:25
12

Add :p after the digits.

Example:

1357  locate pam_loginuid
1358  history
rinzwind@discworld:~$ !1358:p
history
rinzwind@discworld:~$ !1357:p
locate pam_loginuid
rinzwind@discworld:~$ 

Printed to display and not executed.

For using it in BASH you need to do more. Example:
https://tldp.org/LDP/abs/html/histcommands.html

#!/bin/bash
set -o history
var=$(history); echo "$var"   # 1  var=$(history)`

will put all of history into var and you need some more logic to find the command you want.

3
  • OK. This is almost what I'm looking for, but I have to type !555:p, then I have to click the up arrow to get the command on the command line. This is almost as much work as $ fc 555, then Ctl + X. But it is better. If there is not an even better solution, I will come back and give you the credit for the answer. Thank you very much! I am wondering if it's possible to write a script triggered by the # in #555 that will accomplish what I'm looking for. (I'm new to Linux). Commented Mar 26, 2021 at 18:17
  • You will need to do some bash scripting if you want it more fancy that this. The mandatory lines I added to the answer, now you need some filtering on var ;-)
    – Rinzwind
    Commented Mar 26, 2021 at 18:23
  • Thanks again for your help and setting me on the path to writing my own bash commands. That was a great article too you cited. I'll look over these things again when I work on a command to make #555 simulate shopt -s histverify. if histverify gets in my way too much, it's good to know I can fall back on !555:p. Thanks again! Commented Mar 26, 2021 at 19:45
8

If you are using bash, which I presume you are; Type the history number:

$ !555

Then Press: Ctrl + Alt + e, Now the desired command from history is sitting in your prompt waiting to be executed without changing the default behavior of history:

$ command

It also works for aliases, substitutions, expansions and arguments of history say: $ echo !555:1, ~, $HOME, $(echo hi).


This is how I make sure exactly what command from history will be executed before actually running it.

2
  • Thank you! This works great! I will remember it when I get brave enough to turn off histverify! Commented Mar 29, 2021 at 5:49
  • Alt is really the Meta key, so whenever this isn't available, that would be ESC then Ctrl+e. And to remember it, it's e for Expand.
    – jcaron
    Commented Mar 29, 2021 at 9:26
2

edit: I mistakenly said at first "ctrl-f" where it is in fact "ctrl-r" ... (which I use multiple times a day). I edited the correct commands now ...

Not the method you asked, but probably good for what you seem to need to do (ie, find a previous line in history and edit it before entering/executing it again):

# in bash
[Ctrl]+r  Foo 
# This recalls the previous history line containing Foo, in edit mode.
# You can then:
# [Enter] to execute it "as is", and returns to prompt.
#  -or- [Ctrl]+o executes it "as is" + presents the following
#       history line, ready to be executed
#  -or- <Leftarrow> or <Rightarrow> makes that line the current one
#         and you can then edit it before executing it (what OP asked for)
#  -or- [Ctrl]+c to return to the prompt without executing 
#        the currently displayed command line.
#  -or- another [Ctrl]+r search the previous occurrence of Foo
   

That way no need to do history and figure out which history number you needed to edit and another combination to actually retrieve and edit it: [Ctrl]+r Something will find the previous line(s) containing Something for you and present it in edit mode. It is much faster, in general.

Ctrl-o (instead of enter) is especially usefull if you often need to edit 1 command and follow it by a repeat sequence of commands

And nice bonus: this ctrl-r, etc : is often available in other programs (ex: mariadb-server cli [ usefull to retrieve the last 'use' command] , and probably many others). It is probably based on (maybe offered by, or at least using) the "readline" mechanism, but I do not know the details...

2
  • 1
    Yes, thank you! This works great (now that I'm pressing the letter r). I'm a new Linux user just over from Windows and still used to the visual approach. As I get used to not "seeing" what I don't need to see, I'm sure I will progress from using 'histverify', to Ctrl + Alt + E, to not needing to see the history list most of the time and just using Ctrl + R to retrieve commands ready for editing or executing. Thank you so much! Commented Apr 1, 2021 at 16:51
  • @KevinBerry: you're welcome. ctrl-r will become intuitive: if you recall the command you want to see again contained for exemple "vi " or ".csv" or anything:: ctrl-r thatthingyouremember will make it pop out. If it is another line, just another ctrl-r and it goes deeper & deeper back in your history, making that line pop-up. If it is the right one: Enter to execute it 'as is', or : right-arrow to just open it and start editing it (I forgot that part, I'll edit my answer). Welcome to the shell and to these stackexchange sites :) Commented Apr 2, 2021 at 13:50
1
  • You can use the bash built-in command read directly like so:

    read -e -i "!555" -p "${PS1@P}" input; $input
    
  • Or you can add it in a function to your ~/.bashrc like so:

    showhist() {
    
            read -e -i "$*" -p "${PS1@P}" input
            $input
    
    }
    

    and use it like so:

    showhist !555
    

That will show the command at the prompt and you can edit it.... Enter to execute or Ctrl+c to abort.

1
  • 1
    Thank you. I played with this and will look at it again when I work later to write a command that can simulate histverify using #555. Commented Mar 26, 2021 at 19:43

You must log in to answer this question.

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