How to use arguments from previous command?
Asked Answered
S

12

372

I know that Esc + . gives you the last argument of the last command.

But I'm interested in first argument of the last command. Is there a key binding to do so?

On the same lines, is there a generic way of getting the nth argument from the last command? I know that in a bash script, you can use $0, $1 etc., but these don't work on the commandline.

Also, what about iterating through the 0th argument of previous commands, like we can do with the last argument by continuously pressing Esc + .?

Sutherlan answered 24/10, 2010 at 17:22 Comment(0)
T
316

Just as M-. (meta-dot or esc-dot or alt-dot) is the readline function yank-last-arg, M-C-y (meta-control-y or esc-ctrl-y or ctrl-alt-y) is the readline function yank-nth-arg. Without specifying n, it yanks the first argument of the previous command.

To specify an argument, press Escape and a number or hold Alt and press a number. You can do Alt--to begin specifying a negative number then release Alt and press the digit (this will count from the end of the list of arguments.

Example:

Enter the following command

$ echo a b c d e f g
a b c d e f g

Now at the next prompt, type echo (with a following space), then

Press Alt-Ctrl-y and you'll now see:

$ echo a

without pressing Enter yet, do the following

Press Alt-3 Alt-Ctrl-y

Press Alt-- 2 Alt-Ctrl-y

Now you will see:

$ echo ace

By the way, you could have put the echo on the line by selecting argument 0:

Press Alt-0 Alt-Ctrl-y

Edit:

To answer the question you added to your original:

You can press Alt-0 then repeatedly press Alt-. to step through the previous commands (arg 0). Similarly Alt-- then repeating Alt-. would allow you to step through the previous next-to-last arguments.

If there is no appropriate argument on a particular line in history, the bell will be rung.

If there is a particular combination you use frequently, you can define a macro so one keystroke will perform it. This example will recall the second argument from previous commands by pressing Alt-Shift-Y. You could choose any available keystroke you prefer instead of this one. You can press it repeatedly to step through previous ones.

To try it out, enter the macro at a Bash prompt:

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

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

"\eY": "\e2\e."

Unfortunately, this doesn't seem to work for arg 0 or negative argument numbers.

Tungsten answered 24/10, 2010 at 20:4 Comment(6)
When looking for keyboard shortcuts for bash/readline, I like running bind -lp and looking at the current bindings.Halflight
@ChadSkeeters: And -s (new in Bash 4) lists macros created using -x.Tungsten
Note that you can use the digit argument with M-. as well: Alt-3 Alt-Ctrl-y for example equals holding Alt and typing 3.. If you type 3. that multiple times without releasing Alt you go through the third arguments of your previous command lines.Pilewort
@dessert: I say as much in my second paragraph and then show an example.Tungsten
@ChadSkeeters, thanks for the warning that there would be hundreds of entries! Lol.Gnathonic
Alt-3 Alt-. (, Alt-., ...) (cycling through 3rd argument) is what I have been looking for for yearsDraughtsman
A
411

!$ gets the last element of the previous command line argument.

Autism answered 6/1, 2013 at 16:12 Comment(9)
!:3 gets you the third oneHeard
!* gets you all of emLoria
!! gets you the entire last command. Useful if you forgot to use sudo.Elke
!:1-2 gets you all but the last of 3 argumentsKalgoorlie
Alt + . also gets the last element of the previous command line argument (in bash)Loma
Just a word of warning - if you use combined arguments like echo foo{,bar} baz, the command is recorded as printed and expands afterwards. With the above, using echo !:1 after resolves to echo foo{,bar} and then expands to echo foo foobarPedigree
Additionally, combining commands like echo a b c && echo !:2 still count as one command for your history, so echo foo && echo !:2bar won't output foo + foobar, but rather foo and (previous command's second argument)barPedigree
For more information, the reference for the above excellent comments is here: gnu.org/software/bash/manual/html_node/…Gem
While true, that is not a keybinding, which is what the question asked for.Baghdad
T
316

Just as M-. (meta-dot or esc-dot or alt-dot) is the readline function yank-last-arg, M-C-y (meta-control-y or esc-ctrl-y or ctrl-alt-y) is the readline function yank-nth-arg. Without specifying n, it yanks the first argument of the previous command.

To specify an argument, press Escape and a number or hold Alt and press a number. You can do Alt--to begin specifying a negative number then release Alt and press the digit (this will count from the end of the list of arguments.

Example:

Enter the following command

$ echo a b c d e f g
a b c d e f g

Now at the next prompt, type echo (with a following space), then

Press Alt-Ctrl-y and you'll now see:

$ echo a

without pressing Enter yet, do the following

Press Alt-3 Alt-Ctrl-y

Press Alt-- 2 Alt-Ctrl-y

Now you will see:

$ echo ace

By the way, you could have put the echo on the line by selecting argument 0:

Press Alt-0 Alt-Ctrl-y

Edit:

To answer the question you added to your original:

You can press Alt-0 then repeatedly press Alt-. to step through the previous commands (arg 0). Similarly Alt-- then repeating Alt-. would allow you to step through the previous next-to-last arguments.

If there is no appropriate argument on a particular line in history, the bell will be rung.

If there is a particular combination you use frequently, you can define a macro so one keystroke will perform it. This example will recall the second argument from previous commands by pressing Alt-Shift-Y. You could choose any available keystroke you prefer instead of this one. You can press it repeatedly to step through previous ones.

To try it out, enter the macro at a Bash prompt:

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

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

"\eY": "\e2\e."

Unfortunately, this doesn't seem to work for arg 0 or negative argument numbers.

Tungsten answered 24/10, 2010 at 20:4 Comment(6)
When looking for keyboard shortcuts for bash/readline, I like running bind -lp and looking at the current bindings.Halflight
@ChadSkeeters: And -s (new in Bash 4) lists macros created using -x.Tungsten
Note that you can use the digit argument with M-. as well: Alt-3 Alt-Ctrl-y for example equals holding Alt and typing 3.. If you type 3. that multiple times without releasing Alt you go through the third arguments of your previous command lines.Pilewort
@dessert: I say as much in my second paragraph and then show an example.Tungsten
@ChadSkeeters, thanks for the warning that there would be hundreds of entries! Lol.Gnathonic
Alt-3 Alt-. (, Alt-., ...) (cycling through 3rd argument) is what I have been looking for for yearsDraughtsman
L
289

To use the first argument, you can use !^ or !:1

Example:

$ echo a b c d e 
a b c d e
$ echo !^
echo a
a

$ echo a b c d e 
a b c d e
$ echo !:1
echo a
a

Since your question is about using any other arguments, here are some useful ones:

!^      first argument
!$      last argument
!*      all arguments
!:2     second argument

!:2-3   second to third arguments
!:2-$   second to last arguments
!:2*    second to last arguments
!:2-    second to next to last arguments

!:0     the command
!!      repeat the previous line

The first four forms are more often used. The form !:2- is somewhat counter-intuitive, as it doesn't include the last argument.

Litchfield answered 1/9, 2015 at 13:16 Comment(4)
Is there a way to get the second-last item? i.e. get file3 from mv file1 file2 file3 target/?Woodcock
I liked this answer a lot and just for the completeness sake, I suggest to also add a line telling about '!-2' syntax that allows you to access previous to previous command.Skiffle
@Skiffle Also for even more completeness the command '!2' which allows you to access the second entry in the history (if it's still available depending on your history settings). Useful if you display the history number in each prompt.Marceau
There's also !:-2 which gives you everything up until the 2nd argument. In this case echo a b.Bisson
C
69

I liked @larsmans answer so much I had to learn more. Adding this answer to help others find the man page section and know what to google for:

$ man  -P 'less -p ^HISTORY\ EXPANSION' bash
<...>
Word Designators

Word designators are used to select desired words from the event.
A : separates the event specification from the word designator.
It may be omitted if the word designator begins with a ^, $, *, -,
or %.  Words are numbered from the beginning of the line, with the
first word being denoted by 0 (zero).  Words are inserted into the
current line separated by single spaces.

   0 (zero)
          The zeroth word.  For the shell, this is the command word.
   n      The nth word.
   ^      The first argument.  That is, word 1.
   $      The last argument.
   %      The word matched by the most recent ‘?string?’ search.
   x-y    A range of words; ‘-y’ abbreviates ‘0-y’.
   *      All of the words but the zeroth.
          This is a synonym for ‘1-$’.  
          It is not an error to use * if there is just one word in
          the event; the empty string is returned in that case.
   x*     Abbreviates x-$.
   x-     Abbreviates x-$ like x*, but omits the last word.

   If a word designator is supplied without an event
   specification, the previous command is used as the event.
Calvinna answered 10/7, 2014 at 9:18 Comment(0)
P
25

Tested on Ubuntu 18.04


To insert previous arguments:

  • Alt+.: insert last argument from last command.
  • Alt+#+.: insert #nth last argument from last command.
  • Alt+- , # , Alt+., zsh: Alt+-+#+.: insert #nth first argument from last command.

In Linux you can repeat commands to go back in history

Example:

Last command is:

mv foo bar
  • Alt+0+.: insert first argument of last command = mv
  • Alt+2+.: insert last 2nd argument of last command = foo
  • up , Ctrl+w: last command without the last word = mv foo

General shortcuts

  • Ctrl+w: removes last word from cursor
  • Alt+d: removes next word from cursor
  • Ctrl+k: cuts everything after cursor
  • Ctrl+u, zsh: Alt+w: cuts everything before cursor
  • zsh: Ctrl+u: cuts the entire command (In bash you can combine Ctrl+u , Ctrl+k)
  • Ctrl+y: paste characters previously cut with Ctrl+u and Ctrl+k
  • 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 line
  • end or Ctrl+e: move to end of line

To iterate through the arguments in a previous command

only works in zsh

run or add this to your ~/.zshrc

autoload -Uz copy-earlier-word
zle -N copy-earlier-word
bindkey "^[:" copy-earlier-word

Now use Alt+. to go as back as you want, then use Alt+: to iterate through the arguments

Assuming last command is

echo 1 2 3 4 5
  • Alt+.: 5
  • Alt+.+:: 4
  • Alt+.+:+:: 3
  • Alt+.+:+:+:: 2
  • Alt+.+:+:+:+:: 1
  • Alt+.+:+:+:+:+:: echo

source: https://mcmap.net/q/88422/-alt-number-dot-and-alt-comma-in-zsh-and-bash

To see all shortcuts available

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

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

Princessprinceton answered 8/3, 2019 at 19:32 Comment(5)
Alt . on Zsh on Mac is typing 🤔Pledge
Esc . works, even though it only works for the last one. You can't keep typing to go back in time. Maybe it would be worth updating the answer. Thank you very much.Pledge
You could run bindkey -L in zsh to see all shortcuts binded, maybe it it will help pinpoint the issue, or even find other useful commands. In my case for example: the binding Alt . is defined as bindkey "^[." insert-last-word. Ctrl L (to clear screen) -> bindkey "^L" clear-screen. Alt+Ctrl h -> bindkey "^[^H" backward-kill-word (same as Ctrl w to remove last word)Princessprinceton
@Princessprinceton I can also see on bind keys the mentioned copy-earlier-word as bindkey "^[^_" copy-prev-wordSump
Some of these shortcuts depend on terminal used. E.g. in xfce4-terminal Alt-2 switches to the second tab.Hedgepeth
Q
19

!^ may be the command for the first argument. i'm not sure if there is a way to get the nth.

Quietly answered 24/10, 2010 at 17:26 Comment(2)
it is !:n as suggested aboveProlepsis
Is there a way to get the n-th last item, so like !:n, but counting from the end rather than the start?Woodcock
E
16

You can also get arguments from any command in your history!


$ echo a b c d e f g
a b c d e f g
$ echo build/libs/jenkins-utils-all-0.1.jar
build/libs/jenkins-utils-all-0.1.jar
$ history | tail -5
  601  echo build/libs/jenkins-utils-all-0.1.jar
  602  history | tail -10
  603  echo a b c d e f g
  604  echo build/libs/jenkins-utils-all-0.1.jar
  605  history | tail -5
$ echo !-3:4
echo d
d
$ echo !604:1
echo build/libs/jenkins-utils-all-0.1.jar
build/libs/jenkins-utils-all-0.1.jar
Euthenics answered 14/4, 2016 at 17:6 Comment(0)
V
13

!^ will get you the first param, !$ will get you the last param, !:n will get you the nth element.

Verge answered 5/11, 2018 at 22:1 Comment(0)
C
4

Basically it has a use in yanking previous (command's) arguments.

For instance, if the following command is issued:

echo Hello, world how are you today?

then, Hello, will be the first argument, and today? the sixth, that is the last one; meaning it can be referenced by typing:

Alt+6 followed by Ctrl-Alt-6


Ctrl is traditionally denoted as a hat character ^ prepended to keys names, and Alt as M- that is Meta prefix.

So the above shortcut can be redefined as ^My to yank.


Also, there is hats substitution shortcut in the command line:

echo Hello, world!

^Hello^Bye

Bye, world!

to substitute the previous command's first matched string, meaning:

Hello, world! Hello, people!

^Hello^Bye

would result in:

Bye, world! Hello, people!

leaving the second match (hello) unchanged.

Note: Do not leave space between hats, or the operation won't work.


The above is just a shortcut for:

!:s/Hello/Bye

event-level(*) substitution for the first found (matched) string in the previous command, while prefixing the first part with the g switch will apply to the whole line globally:

echo Hello, world! Hello, people!

!:gs/Hello/Bye

Bye, world! Bye, people!

as usually being done in other related commands such as sed, vi, and in regex (regular expression) - a standart way to search (match string).

No, you can't do !:sg/Hello/Bye or !:s/Hello/Bye/g here, that's the syntax!


  • ! is for events; event might be understood as command output or operation done in the commands history.

That's what I understood by using it myself and trying things on my own from what I read from various sources including manual pages, blogs, and forums.

Hope it will shed some light into mysterious ways of bash, the Bourne-Again shell (a play on sh shell, which itself is called Bourne shell after its inventor's last name), what is default shell in many distributions including servers (server OS's).

Ciliary answered 1/5, 2017 at 17:48 Comment(0)
A
1

The method described at the end of the accepted answer also works with the zeroth argument for me. I have these lines in my ~/.inputrc:

"\en": "\e0\e."
"\em": "\e1\e."
"\e,": "\e2\e."

\e2\e. has the advantage over \e2\e\C-y that it cycles through previous commands if it is pressed repeatedly instead of inserting the second argument of the previous command multiple times.

To insert the whole previous command, you can type !!\e^. \e^ is shell-expand-line.

Antipas answered 6/12, 2015 at 15:27 Comment(0)
C
1

For pasting 1th argument, press and hold down Alt key, and while it is down, hit the '1' key followed by the '.' key.

For pasting n-th argument, replace the '1' key above with the corresponding number key.

If this does not work, your terminal emulator may be catching the Alt key before it gets to shell. Some terminals (xfce4-terminal) allow turning off the "Alt-" shortcuts in the configuration file.

Credit to Jonas Eberle, I've fished this out from his comment to another answer here.

Camire answered 9/5, 2022 at 21:29 Comment(0)
F
0

If you are on a mac you will tend to get extended characters with ctrl+letter. I have my right-of-space-bar-option key defined as meta in my terminal (iTerm2) set up. This means I use the key to navigate by word and pull parameters from previous commands.

Forensics answered 16/2, 2020 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.