One of the features of bash I’ve too long overlooked is its history expansion. In this post I’ll show a few examples to get a grip at it.
Recall a previous line
- Recall the last line
kattoo@roadrunner ~ $ date Sun Mar 28 18:35:12 CEST 2010 kattoo@roadrunner ~ $ !! date Sun Mar 28 18:35:13 CEST 2010 kattoo@roadrunner ~ $
- Recall the n-th last line :
kattoo@roadrunner ~ $ echo 1 1 kattoo@roadrunner ~ $ echo 2 2 kattoo@roadrunner ~ $ echo 3 3 kattoo@roadrunner ~ $ !-3 echo 1 1 kattoo@roadrunner ~ $
- Recall the n-th line of the history
kattoo@roadrunner ~ $ history [...] 533 date 534 date 535 echo 1 536 echo 2 537 echo 3 538 echo 1 539 history kattoo@roadrunner ~ $ !536 echo 2 2 kattoo@roadrunner ~ $
Re-using previous command line arguments
- Re-use all the arguments of the previous command
kattoo@roadrunner ~ $ touch test-file.txt kattoo@roadrunner ~ $ scp !* remote:/tmp scp test-file.txt spaghetti:/tmp test-file.txt 100% 0 0.0KB/s 00:00 kattoo@roadrunner ~ $
- Re-use the m-th argument from the n-th previous command line
kattoo@roadrunner ~ $ echo 1 2 3 1 2 3 kattoo@roadrunner ~ $ echo !-1:2 echo 2 2 kattoo@roadrunner ~ $
- Re-run the previous command changing occurrences of X by Y
kattoo@roadrunner ~ $ echo test test kattoo@roadrunner ~ $ ^test^replaced echo replaced replaced kattoo@roadrunner ~ $
That’s about it… those are what I consider to be the most useful history expansion features of bash.
Do you have any other you find especially useful ? Share them in the comments !
Your example is less strict than it could be. I’d recommend using $_ instead of !*. This would make it compatible with something like,
$ some_filter input_file -o output_file
$ scp $_ remote:/tmp
Whereas ‘scp !* remote:/tmp’ would expand to ‘scp input_file -o output_file remote:/tmp’.