7

I am using Ubuntu and I'd like to repeat a bunch of commands I performed. I tried something like

for i in $(seq 2006 2013); do \!$i; done;

but failed, since shell tries to execute a command '!2006'.

man history

also didn't reveal to me how to repeat a range of commands.

7
  • cannot find anything similar in Event designators
    – fedorqui
    Commented Jul 11, 2014 at 13:59
  • Yes, exactly. This is all I found too, in man history. Commented Jul 11, 2014 at 14:02
  • 1
    That's curious; you seem to be right, even though fc 2006 2013 will give you 8 command lines to edit and then execute whatever commands you leave in the file after exiting the editor. OK; since bash is playing tricks with us, we'll have to play tricks on bash. Tell bash to use : as the editor: fc -e : 2006 2013. Commented Jul 11, 2014 at 14:38
  • 1
    Yes, this works. I also managed to use fc -s $i in the loop. I didn't know fc. Thanks for the hint. If you create an answer out of you comment, I will vote for it, of course. :-) Commented Jul 11, 2014 at 14:40
  • 1
    Yes that's right, I was also able to make this work: for i in {2006..2013}; do fc -s $i; done But @JonathanLeffler: trick of fooling BASH was also great using fc -e : :)
    – anubhava
    Commented Jul 11, 2014 at 14:51

2 Answers 2

10

If you are using bash (or ksh), the fc built-in allows you to manipulate history in various ways.

fc -l                   # list recent history.
fc -l      2006 2013    # list commands 2006..2013
fc         2006 2013    # launch editor with commands 2006..2013; executes what you save
fc -e pico 2006 2013    # launches the editor pico on command 2006..2013
fc -e -    2006 2013    # Suppresses the 'edit' phase (but only executes the first listed command)
fc -e :    2006 2013    # Launches the ':' command (a shell built-in) as the editor

The classic technique in ksh is to use an alias alias r='fc -e -', but because of the behaviour of bash, it is necessary to twist its arm a little harder and use alias r='fc -e :' instead.

4
for i in $(seq 2006 2013); do \!$i; done; 

in your code, you may think ! is like ! in bash command line, but here "!" with the "$i" become a string like string command "!2006, !2007 ... !2013" but actually there is no command named "!2006" "!2006" in whole is a command name.

in Bash ! is a event designator. when you use !2006. it is explained as "reference to command 2006" but not use command "!2006".

! is always left to right execute command.

for more information please visit http://www.gnu.org/software/bash/manual/bashref.html#Event-Designators

I try the following way to get the same result:

for i in $(seq 2006 2013); do  fc -e - $i; done;

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