21

If you want to re run a command with the same arguments you can do something like this:

vim long_filename
cat !$                     #same as 'cat long_filename'

This saves having to type out the previous argument again when it is passed to cat.

However, how would I pass arguments that are not the same to the last run script/command?

long_annoying_script_name arg1 arg2
? arg3 arg4                                  #? signifies shortcut symbols such as '!$'

Of course I could just press the 'up' arrow and delete the arguments and type the new ones, but is there a shorter/faster way?

I DO NOT want to assign an alias.

0

2 Answers 2

29

!:0 should do the trick. From the zsh documentation:

   Word Designators
       A word designator indicates which word or words of a given command line
       are to be included in a history reference.  A `:' usually separates the
       event specification from the word designator.  It may be  omitted  only
       if  the  word designator begins with a `^', `$', `*', `-' or `%'.  Word
       designators include:

       0      The first input word (command).
       n      The nth argument.
       ^      The first argument.  That is, 1.
       $      The last argument.
       %      The word matched by (the most recent) ?str search.
       x-y    A range of words; x defaults to 0.
       *      All the arguments, or a null value if there are none.
       x*     Abbreviates `x-$'.
       x-     Like `x*' but omitting word $.

(It works with bash, too.) There’s also !-1 if you find that more convenient to type.

3
  • 2
    +1 - a shortcut for !!:0 arg3 arg4 documentation: Bash History word designators Commented Jul 4, 2016 at 3:52
  • @hdl: What would you want it to do in a script – refer to other parts of the script, or to the user’s history?
    – Ry-
    Commented Jan 12, 2018 at 21:20
  • From the user's history. I used fc -ln -1 to get the previous command line from history, but then I had to parse it into a single command word, then single subcommand (for git), then args, before I could actually run it. Maybe there are some simpler solutions...
    – hdl
    Commented Jan 12, 2018 at 21:58
15

#TL;DR Alt+0+.: inserts last command without the arguments


Tested on Ubuntu 18.04 with the default keybinding settings (i.e Emacs keybindings)


You can combine keyboard shortcuts

Let's consider the last command to be:

mv foo bar

up , Ctrl+w: last command without the last word = mv foo

Alt+0+.: first argument of last command = mv

Some useful shortcuts:

  • Alt+.: insert last argument from last command (repeat to go back in history)

  • Alt+number+.: insert #nth last argument from last command (repeat to go back in history)

  • Alt+- , number , Alt+., zsh: Alt+-+#+.: insert #nth first argument from last command (repeat to go back in history)

  • Cut commands (relative to cursor's position)

  • Ctrl+w: cuts last word

  • Alt+d: cuts next word

  • Ctrl+k: cuts everything after

  • Ctrl+u, zsh: Alt+w: cuts everything before

  • zsh: Ctrl+u: cuts the entire command (In bash you can combine Ctrl+u , Ctrl+k)

  • Ctrl+y: paste characters previously cut with any Cut command. In bash You can chain cut commands, and Ctrl+y will paste them all.

  • Ctrl+_: undo last edit (very useful when exceeding Ctrl+w)

  • Ctrl+left: move to last word

  • Ctrl+right: move to next word

  • home or Ctrl+a: move to start of command

  • end or Ctrl+e: move to end of command

To see all shortcuts available

  • bash: bind -lp
  • zsh: bindkey -L

Unfortunately there are some limitations

"words" only includes a-zA-Z characters, so any symbol character will stop word-shortcuts.

So if last argument was a url and you want to erase it with Ctrl+w it will be a pain.

E.g: curl -I --header "Connection: Keep-Alive" https://stackoverflow.com/questions/38176514/re-run-previous-command-with-different-arguments

To erase that url using Ctrl+w, you'd have to repeat it 12 times.


It would be great to have similar shortcuts that only stops at the space character


I'm keeping this up-to-date here: https://github.com/madacol/docs/blob/master/bash-zsh_TerminalShorcuts.md

3
  • 2
    This answer presumes emacs keybindings. Commented Jul 2, 2019 at 16:18
  • 1
    @WilliamPursell What does it mean?. Any example where I wouldn't presume it? I've only tested this on Ubuntu, with bash and zsh
    – Madacol
    Commented Jul 2, 2019 at 16:42
  • 3
    emacs key bindings are the default setting. However, if you change to vi key bindings (in bash, with set -o vi, or by modifying ~/.inputrc), the keystrokes are completely different. Commented Jul 2, 2019 at 16:49

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