Within the shell, typing ALT+. or using !$ recalls the last passed argument of the previous command. I use this all the time, but how do you do that when you detached the previous command?

$ do-something foo a_long_file_name &

How do I get a_long_file_name on the prompt, and not the ampersand?


\e-\e. (or pressing - and . while holding alt/option) inserts the second last word.

Similarly, \e-2\e. inserts the third last word, and \e2\e. inserts the third word.


Using history expansion, you can access the words of the previous command with !:n where n starts at 0 with the command name. !^ is equivalent to !:1. In this case, you want !:2

$ echo foo bar &
[1] 10750
foo bar
$ echo !:2
echo bar
[1]+  Done                    echo foo bar
  • The Csh history mechanism doesn't replace the argument on the Bash command line, though. – tripleee Jun 17 '13 at 8:19
  • True, it's a placeholder only. – glenn jackman Jun 17 '13 at 11:02

You do $_.

echo 'hey there' &
echo "$_"


hey there
hey there
  • Does not work for me using bash 4.3.$ echo 'hey there' & hey there $ echo "$_" $ – Bernhard Aug 17 '14 at 7:24
  • Works without &, but not when running in the background. – kenorb Aug 18 '16 at 9:22

The answers of glenn and Lauri are correct, but they require too much typing IMO. Finally I came up with the following solution: C-j looping through the arguments of the previous command (excluding the ampersand), from the last one to the first one. This is very practical! Here is how to do that:

Write the following bash script:


cj_hist=$(builtin history | tail -n1)
cj_num=$(cut -f1 -d\  <<< $cj_hist)

if [[ $cj_old_num -eq $cj_num ]]
  cj_args=$(cut -f3- -d\  <<< $cj_hist)

[[ $cj_cnt -le 0 ]] && cj_cnt=${#cj_args[*]}
let cj_cnt--

if [[ $cj_cnt -eq -1 ]]
  bind '"\ez":""'
  # bind -m vi-insert '"\C-o":""'
  bind '"\ez":"'$cj_killw${cj_args[$cj_cnt]}'"'
  # bind -m vi-insert '"\C-o":"'$cj_killw${cj_args[$cj_cnt]}'"'


Put this in your ~/.bashrc:

 bind -x '"\ew": source ~/foo.sh'  # ~/foo.sh is the script's path
 bind '"\C-j":"\ew\ez"'
 # bind -x '"\C-h": source ~/foo.sh'      # vi-users: no mess
 # bind -m vi-insert '"\C-j":"\C-h\C-o"'  # with escapes

NB: Since we source the script, we have to use variable names that are not commonly used, hence the prefix cj_. Of course, you can use another prefix.

  • It makes me chuckle when 3 characters is too much typing. As soon as the previous command has more than 3 arguments, I win!!!1! :) – glenn jackman Jun 17 '13 at 11:03
  • 1
    C-j C-j C-j C-j may be faster to type than :!5 though, and I don't have to count the arguments. You know, I am doing silly things to type fewer characters or to give my brain a rest, such as: alias l=ls :-) Laziness is the biggest factor of progress. – BertS Jun 17 '13 at 12:13
  • Prefix your local variables with local to restrict scope; and since you're sourcing it, drop the #! line. – Rich Oct 6 '17 at 21:52

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.