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.

8
  • 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 5, 2018 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. Jan 5, 2018 at 16:25
  • @Philippos Just noticed that Ctrl-R takes me to the second command, not the first. Jan 5, 2018 at 16:35
  • Come on! You just invented the echo ssh -i line to exclude using Ctrl-R!
    – Philippos
    Jan 5, 2018 at 16:36
  • Sorry about it. I just realized that when you posted that comment, my edit has not even started. Jan 5, 2018 at 16:41

2 Answers 2

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

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.

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

1
  • 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. Jan 5, 2018 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.

You must log in to answer this question.

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