84

I use !n where (n) is the line number for executing a line in the history file I want executed at the command prompt which I find via history|less.

But there is a command line history event I wish to manually modify. How can I insert into the command line a history events contents without it actually executing so I can modify and then press return?

Best,

8 Answers 8

108

To request that the command be printed rather than executed after history substitution, add the :p modifier, e.g. !42:p. The resulting command will also be entered in the history, so you can press Up to edit it.

If you have the histverify option set (shopt -s histverify), you will always have the opportunity to edit the result of history substitutions.

The fc builtin gives limited access to history expansion (no word designators), and lets you edit a previous command in an external editor.

You can use !prefix to refer to the last command beginning with prefix, and !?substring to refer to the last command beginning with substring. When you know what you're looking for, this can save a lot of time over history | less.

Another way to search through previous history is incremental search: press Ctrl+R and start entering a substring of what you're looking for. Press Ctrl+R to go to the previous occurence of the search string so far and Ctrl+S if you've gone too far. Most keys other than Ctrl+R, Ctrl+S, Backspace and ordinary characters terminate the incremental search and have their usual effect (e.g. arrow keys to move the cursor in the line you've reached, Enter to run the command).

5
  • 10
    You will need to do stty -ixon before Ctrl-s will work. Nov 15, 2010 at 23:51
  • @Dennis: Wow, modern terminal emulators don't do this by default? <test> You're right, even gnome-terminal in Ubuntu has flow control! Nov 16, 2010 at 0:05
  • I don't know why they still do. It's impossible to catch something while it's scrolling. By the time you press Ctrl-s, you've got a prompt again. And slow serial connections are mostly a thing of the past. Nov 16, 2010 at 0:43
  • @Dennis's point about Ctrl-s is important, otherwise one gets stuck as I did. Apr 27, 2011 at 12:35
  • Should you get stuck with Ctrl-s, then Ctrl-q will resume the flow. The stty -ixon mentioned is the solution to prevent getting stuck in the first place and enable the Ctrl-s to make it to the shell.
    – Chris
    Aug 17, 2020 at 5:33
22

Another small one: Alt+#

comments out the current line and moves it into the history buffer.

So when you're assembling a command line and you need to issue an interim command to e.g. find a file, you just hit Alt+#, issue the other command, go up in the history, uncomment and proceed.

2
  • 4
    Also Esc, # works
    – Zombo
    Jul 8, 2018 at 3:57
  • 1
    and you can actually type it on a mac (hold shift, press ESC and # together), unlike the other ket combo (fn+alt+shift+#) ;-)
    – 0xF2
    Oct 4, 2018 at 3:12
9

You can use magic space to expand history before hitting enter. In your .inputrc, map space to magic space:

$if Bash
     Space: magic-space
$endif

Now, whenever you type a space after a history specification, it'll be immediately expanded - handy if you want to edit it, too!

8

Take a look at the history-expand-line command, bound to Alt+^ by default. It will expand the line in-place which you can then edit.

5

I normally use Ctrl+r to search and then Ctrl+e to go to the end of the line without executing.

1
  • 1
    Baffling this answer is not marked as correct. It does exactly what the question asked for and what I was looking for. Apr 21, 2020 at 6:54
4

Using Ctrl+r you can search history:

pbm@tauri ~ $ 
(reverse-i-search)`xran': xrandr -o normal

Any command that you find could be edited...


I think that I found exactly what you need: run shopt -s histverify and next time when you want to use !n command will be not executed but only put to command line...

12
  • 1
    You have to execute a command before it can be searched with Ctrl+r, not what Vass is asking for.
    – phunehehe
    Nov 15, 2010 at 15:59
  • 1
    I don't understand how this doesn't do what he asks. I would add that if you want to first edit the command before running it, you can simply hit TAB once you have found the right command.
    – Steven D
    Nov 15, 2010 at 16:04
  • 2
    So the procedure would be, (1) Ctrl+r, (2) type until you find command, (3) TAB, (4) edit command, (5) ENTER.
    – Steven D
    Nov 15, 2010 at 16:06
  • 1
    @phuenhehe: "But there is a command line history event I wish to manually modify"
    – pbm
    Nov 15, 2010 at 16:08
  • 1
    Won't !n:p work?
    – alex
    Nov 15, 2010 at 19:07
1

I have often wanted this. When I used csh (and tcsh), I had an idiom:
!:88*:p

This idiom inserts "word 88 through the last word" of the previous command at the point where you're typing on the current command line, which is typically the end. In csh, it is not an error for such an expression to produce no words. That is, there need not be a word 88, nor any that follow it. If there is no word 88, this adds no words to the end of the command being typed, and then pushes the resulting command line into the history without execution.

As you probably know,
* ! (like !! and !-1) is the previous command;
* :88 is word 88 (the first word -- typically the command -- is zero) and csh would require such a word exist, but ...
* :88* is all the words starting at word 88, and then csh does not require the word to exist;
* :p means print, but do not execute the command line.
With or without the :p, the command line is added to the command history.

"Why 88?" you wonder? Because it is the same key as the * I'll need. If you have commands that long, perhaps !:888*:p is what you need. Sorry this doesn't work with bash AFAIK. Bash will merely say bash: :88*: bad word specifier

Fun fact: your command does not usually need to be first.
> /tmp/foo echo My command is word 3
is valid in bash and csh.

1
  • Since the question is tagged for bash, it might be good to start with saying that your solution works only in (t)csh.
    – zagrimsan
    Jul 31, 2017 at 7:34
1

If you're a vi user, you could set vi as the line editor, and use vi commands to move around the shell history and edit the line before executing.

$ set -o vi # add this to .bashrc
$ [Esc]<history line number>[Shift-g]
# edit the line and hit [Enter] to execute

This way you don't need to remember another way to edit the command line. It works for emacs too.

This is how you search the history using regex:

# find commands starting with cd
$ [Esc]/^cd[Enter]
# press [n] to go to next line (up)
# press [Shift-n] to go to previous line (down)
1
  • Whilst this is not an immediately intuitive answer for most people, it's a good solution for those that put the time in!
    – Chris
    Aug 17, 2020 at 6:37

You must log in to answer this question.

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