Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question

4 Answers 4

\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.

share|improve this answer

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
bar
[1]+  Done                    echo foo bar
share|improve this answer
    
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

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:

#!/bin/bash

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

if [[ $cj_old_num -eq $cj_num ]]
then
  cj_killw='\x17'
else
  cj_args=$(cut -f3- -d\  <<< $cj_hist)
  cj_args=${cj_args%&}
  cj_args=($cj_args)
  cj_cnt=0
  cj_killw=''
fi

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

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

cj_old_num=$cj_num

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.

share|improve this answer
    
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
    
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

You do $_.

echo 'hey there' &
echo "$_"

OUTPUT

hey there
hey there
share|improve this answer
    
Does not work for me using bash 4.3.$ echo 'hey there' & hey there $ echo "$_" $ –  Bernhard Aug 17 at 7:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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