Ubuntu – Bash history keyboard shortcut for !*

bashcommand lineshortcut-keys

In Bash, there are some handy operators to repeat parts of the last command:

  • !^ expands to the first argument of the previous command, e.g.,

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
    
  • !$ expands to the last argument of the previous command, e.g.,

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
    
  • !* expands to all arguments of the previous command, e.g.,

    $ echo one "two three"
    one two three
    $ echo !*
    echo one "two three"
    one two three
    

(As far as I understand, these are syntactic sugar for !!:^, !!:$ and !!:* respectively, where !! is an event designator that expands to the previous command, and ^, $ and * are word designators, see the Bash Reference Manual or man bash.)

These are often quite handy. But it gets even cooler with keyboard shortcuts:

  • When you hit Alt+. or Alt+_, the last argument of the previous command is inserted in the current command, similarly as if you had written !$ at that point.

  • It is also possible to hit Alt+Ctrl+y to insert the first argument of the previous command, as if you had written !^ at that point.

(See the GNU Readline Library or info readline.)

I tend to prefer the keyboard shortcuts over Bash's history operators, because I can see what I'm inserting before I actually execute the command. However, there does not seem to be a shortcut that enables me to insert all the words of the previous command, i.e., one that does !*'s job. At least I could not find it.

Is there such a shortcut? If not, is it possible to configure the readline library to add one, and how?

Best Answer

If you look at the output of the following command:

bind -l

or better to:

bind -l | grep arg

you can see that doesn't exist any readline function for all arguments like is, for example, yank-last-arg for last argument - which can insert last argument to the previous command (the last word of the previous history entry). So, if such a function doesn't exists, most probably doesn't exist a shortcut to accomplish what you wish.

Let's try to crate one approached to your request...

First, look for example at the output of the following command:

bind -p | grep yank-nth-arg

The output is:

"\e\C-y": yank-nth-arg

and can be translated as follow: yank-nth-arg (which insert the first argument to the previous command - with an argument n, insert the nth argument from the previous command) is bound to Alt+Ctrl+y.

In the same way can be interpreted any line from the output of bind -p command.

Now play attention at the following scenarios:

  • If you set the following binding:

    bind '"\ea": "\e2\e."'
    

    Alt+A will be mapped to Alt+2Alt+. which is mapped to insert the second argument of the previous command. So, after when you press Alt+A, the second argument of the previous command is inserted in the current command.

  • If you set:

    bind '"\ea": "\e1\e. \e2\e."'
    

    After when you press Alt+A, the first two arguments of the previous command is inserted in the current command. If the number of the arguments from the previous command is maximum 2, of course all of the previous command is inserted in the current command.

  • If you set:

    bind '"\ea": "\e1\e. \e2\e. \e3\e."'
    

    After when you press Alt+A, the first three arguments of the previous command is inserted in the current command. If the number of the arguments from the previous command is maximum 3 (as in your case), of course all of the previous command is inserted in the current command.

  • And so on.

For first 10 arguments, you can use:

bind '"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."'

And I think that this is long enough as far as I don't use too often commands with so many arguments.

To make it persistent, add the following line line to your ~/.inputrc file:

"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."

In this example I chose Alt+A to insert all arguments (if the number of arguments is not greater than 10) of the previous command, but you can chose any other combination you with by replacing in the previous command the \ea string.

Resources: