We all know that !! can repeat the last command you do in bash.

But sometimes we need to do some operation like

$ python test.py
$ vim test.py

$ python test.py # here is where I need to repeat the second proximate bash command

I can use up-arrow key to do that, but that requires me to move my right hand away to an uncomfortable position. So I'm wondering if there is a command which like !! would work?

  • Use Ctrl+P in emacs mode (default), or k in vi-mode if you don't want to reach for the up key. – Stéphane Chazelas Aug 20 '14 at 9:48
  • I’d actually write both commands in one line like vim test.py && python test.py to avoid fiddling with multiple commands in history, but you can simply bind "\ep": previous-history in your ~/.inputrc so you could press Alt+p instead of up key. – tijagi Aug 20 '14 at 13:00

You can use !-2:

$ echo foo
$ echo bar
$ !-2
echo foo

That may not help with your right-hand situation.

You can also use !string history searching for this sort of case:

$ python test.py
$ vim test.py
$ !py
python test.py # Printed, then run

This may be more convenient to use. It will run:

the most recent command preceding the current position in the history list starting with string.

Even just !p would work. You can use !?string to search the whole command line, rather than just the start.

  • It's much better! since arrow keys needs to move your entire wrist, and !-2 only requires finger movements, excellent, Michael. Wow, just read the second part, it's out of my expectation. You are a magician! – Zen Aug 20 '14 at 8:38

More fun is available. Say you want to keep operating on a file (as above, where you're using test.py, repeatedly):

cp foo.py thing.py
edit $_
python $_
  • Copy an existing file to thing.py
  • Edit (vim, emacs - though why you'd be using a command line if you were running Emacs-OS, I have no idea) thing.py - the last word in the previous command line
  • python thing.py
  • Edit thing.py
  • Edit foo.py

History manipulation is such fun. Try man history. Note that the quest to re-use history can result in typing far more than the command itself would. The final command substitution, where I replace thing.py by foo.py is one such example. Fewer characters to just type in the command and name. :)

The history substitution is also why you get strange messages when you try:

$ echo "This is a disaster!"
-bash: !": event not found

The exclamation mark is being consumed as a history reference, and it can't find a previous command with a double quote.

  • By the way, If I got echo 'xxx', how do I substitute each 'x' into 'y'? – Zen Aug 20 '14 at 9:32
  • Substituting a string for another string? Just that? !!:1gs/x/y/ – JezC Aug 20 '14 at 9:44
  • Though personally, I'd be looking at $(echo !! | sed -e s/x/y/g) – JezC Aug 20 '14 at 9:51
  • using sed would be too clumsy, can I add some parameter or symbol in ^x^y to do that job? – Zen Aug 20 '14 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.