Anyone who has had an introductory unix course should know about the bash shell's "history" command, which gives you a numbered list of commands that you've run previously.
You can execute one of those commands again by doing:
$ ![number] (for a particular command you've seen on the history list)
or
$ !! (for the previous command/last command in the history list)
One thing that I didn't learn in any class, but did find out about from a co-worker, several years ago, was history substitution. It's easy to run the previous command with minor changes, by using a caret-delimited substitution expression. Here's a very simple example:
view a file:
$ cat spugbrap.txt
then, edit that same file:
$ ^cat^vim^
that gets expanded to (and executed as):
$ vim spugbrap.txt
I've used this feature countless times since learning about it, but it always suffered from a limitation: If the pattern you're trying to match occurs multiple times in the previous commandline, this subtitution method only replaces the first occurrance of it. So, I recently decided to find out how to substitute multiple occurances, since I was sure there had to be an easy way. Here's one way I found:
watch a couple of tomcat log files continuously:
$ tail -F ~/tomcat/logs/stdout_20060704.log ~/tomcat/logs/stderr_20060704.log
The next day, the log file names are different, because they're date-based. so I want to change 20060704 to 20060705, and it needs to happen twice because the date occurs twice in that commandline. No problem! Assuming the previously executed command was the "tail" commandline, above, simply enter this:
$ !!:gs/20060704/20060705/
that gets expanded to (and executed as):
$ tail -F ~/tomcat/logs/stdout_20060705.log ~/tomcat/logs/stderr_20060705.log
What if my previous command was long, and I need to make multiple substitutions with multiple strings?
previous command:
$ tail -F stdout_20060704.log stderr_20060704.log host-manager.2006-07-04.log catalina.2006-07-04.log admin.2006-07-04.log localhost.2006-07-04.log manager.2006-07-04.log jakarta_service_20060704.log
to change the dates, which occur in two formats:
$ !!:gs/20060704/20060705/:gs/2006-07-04/2006-07-05/
If the command I want to run (with substitutions) was not the previous command, but some other command that appears in the numbered list from running 'history', put the history line number between the exclamation point and the colon:
$ !123:gs/oldstr/replacementstr/
For more information about this, and other bash history manipulation capabilities, check out:
Bash Features - Using History Interactively