Learning history expansion tricks in bash —02 July 2013
Have you ever read the full
man bash? Me: nah-uh… It’s way too much! Deep deep deep stuff.
In any tool, I tend to focus on a small set of tricks with very high practical value. For example these bash features:
- Backward search command history with
- Delete words backwards with
C-wor forward with
ESC-dand paste them later with
- Jump around on the command line with
ESC-f, or actually use
C-was a form of jumping back fast, or
C-cto cancel and re-type
And so on. I use these in literally every single minute I spend in the shell, so they were really well worth memorizing! (See my slides on these and similar time-saving tricks on SpeakerDeck.)
I rarely memorize new tricks. There’s a sweet spot on the effort-benefit curve, beyond which the benefits are not that great. But from time to time I discover something new that might be worth learning and adding to my arsenal. Right now some history expansion tricks look pretty damn handy.
The event designator
!! is a type of so-called event designator: it refers to the previous command. I use this to save complex commands for later use, for example this operation on an Apache log file (get the number of requests per user agent):
cat access.log | cut -d\" -f6 | sort | uniq -c | sort -n echo "!!" >> later.sh
This is not a perfect solution in this case, because the backslash there will disappear in the output, and in general it won’t work if there are unescaped double quotes in the command. However, there are many use cases when it can simplify my typing.
The word designators
As the man page says: Word designators are used to select desired words from the event. These two are expanded to the last argument and the first argument, respectively. They are relatively easy to remember if you consider the meaning of
^ in regular expressions.
A typical example situation:
less /path/to/some/file rm /path/to/some/file
Doing this and similar actions involves a bit too many key strokes:
ESC-d + [type “rm”]. Easier to do like this:
less /path/to/some/file rm !$
A similar feature is
ESC-. which pastes the last argument while editing, so you can make changes before running the next command.
You can read more about these and similar tricks in
man bash, under HISTORY EXPANSION.