1

Whenever I need to type a long command I find that the exclamation mark to refer to history very handy. For example, !ssh can be used to invoke the last ssh command I used. However I cannot get it to work when space-delimited arguments are added to the search.

By executing !ssh -i, I expect to the last command starting with the string "ssh -i" to be executed. However, the actual command that is invoked is the last ssh command with whatever argument, and then "-i" was appended to the command.

I can use !?ssh -i? but that is meant to do something different and I believe there should be a simple way to achieve this. I am also reluctant to type history|grep ... every time.

So how can I refer to a command in history that starts with a string containing space, as stated above?

Edit It seems that I have not explained the question clear enough. Let's say I have the following history

ssh -i identity host1
echo ssh -i
ssh host2

now if I run !ssh, the third command, namely ssh host2 will be executed. I expect to type !ssh -i to get the first command executed, but ssh host2 -i is executed instead (which results in an error). I can use !?ssh -i? to execute the first command only if the second command doesn't exist.

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
Weijun Zhou
  • 3,368
  • 1
    Why not use ctrl-Rssh -i instead? I never use history expansion, but always history search, because (a) it always works the same way and (b) it keeps me from mistakes because I can see the line to execute before I really do it and (c) I can do set +H by default, so the bad implementation of bash history expansion won't mess up my scripts. – Philippos Jan 05 '18 at 16:20
  • Thank you for your suggestion. It makes sense to me. I am just not yet used to Ctrl-R. I will consider switching to it. For the "never use history expansion" part, history expansion is useful if you want to embed it into a larger command. – Weijun Zhou Jan 05 '18 at 16:25
  • @Philippos Just noticed that Ctrl-R takes me to the second command, not the first. – Weijun Zhou Jan 05 '18 at 16:35
  • Come on! You just invented the echo ssh -i line to exclude using Ctrl-R! – Philippos Jan 05 '18 at 16:36
  • Sorry about it. I just realized that when you posted that comment, my edit has not even started. – Weijun Zhou Jan 05 '18 at 16:41
  • Does ssh -i followed immediately (no newline) by the PageUp key do what you want? – Mark Plotnick Jan 05 '18 at 18:19
  • It doesn't work in the current state. Maybe I need to put something in .inputrc? – Weijun Zhou Jan 05 '18 at 21:55
  • Yes it works now after I put two lines in .inputrc. Thank you. – Weijun Zhou Jan 05 '18 at 22:08

2 Answers2

1

I believe you want to change the default behavior of bash's HISTCONTROL. From this post: Why is bash not storing commands that start with spaces?

HISTCONTROL

<p>A colon-separated list of values controlling how commands are saved on the history list. If the list of values includes ignorespace, lines which begin with a space character are not saved in the history list. A value of ignoredups causes lines matching the previous history entry to not be saved. A value of ignoreboth is shorthand for ignorespace and ignoredups.</p>

If you want to skip the ! and allow for spaces then I suggest you try a shell other than bash. Fish shell works perfectly for what you're asking :)

sudo apt-get install fish

to try it from your bash shell just type, 'fish'

If you like it you can persist it with:

chsh -s /usr/bin/fish

David Aubin
  • 183
  • 1
  • 1
  • 9
  • Thank you for your answer, but I am referring to spaces in the middle of the command, not the spaces at the beginning of the command. – Weijun Zhou Jan 05 '18 at 16:16
0

Thanks to the comment by Mark Plotnick. I have found a solution. Although it is not using bash history expansion. (I believe using bash history expansion to achieve this is impossible after reading [section 9.3.1 of bash reference manual].(https://www.gnu.org/software/bash/manual/html_node/Event-Designators.html)

The solution is to put the following lines in ~/.inputrc, or uncomment the corresponding lines in /etc/inputrc for global effect.

"\e[5~": history-search-backward
"\e[6~": history-search-forward

The corresponding code can be found by pressing CtrlV and then the PageUp key, and the commands are taken from section 8.4.2 of bash manual.

After that I can use PageUp key to go to the first command as Mark commented.

Weijun Zhou
  • 3,368