There are some things in every profession or area of expertise that seem so obvious to you and most people around you. However, there was a point in your career where you did not know this yet and somebody taught you.
A brief discussion on the MacAdmins Slack yesterday led to such a moment. A
bash shortcut that seems so obvious to me and probably to many who read this, but again, not everyone knows. And it was someone’s lucky ten thousand moment to learn an wonderful shell shortcut:
Re-visit your (shell) History
bash shell remembers a certain number of commands that you entered. This way you can ‘recall’ them with the up arrow or the ctrl-R keystroke.1
There are also history substitutions to save typing. And not only do they save typing but these automations, like tab-completion will make you type less errors.
Sudo Make me a Sandwich2
So imagine you typed
$ profiles -P profiles: this command requires root privileges
and the system helpfully reminds you that you need
root privileges to run this. You could retype the entire command after
sudo. You could also hit up-arrow, ctrl-a and type
sudo[space][return], which is some improvement.
Or you just type
$ sudo !! sudo profiles -P Password: There are no configuration profiles installed
The shell will substitute the
!! (‘bangbang’) with the previous command. The shell will print the entire command after the substitution (this can be really helpful when things don’t work as expected) and then immediately execute the full command.3
Personally, I only ever use this with
sudo. I could imagine there are other uses, maybe with
ssh user@host -c.
You can also just type
!! to repeat the last command, I find ‘up-arrow, return’ to be more intuitive (and one keystroke less).
The other history substitution I use is more specific, but still has its uses. The shell substitutes
!$ with the last used argument. The catch here is that if the previous command had multiple arguments,
!$ will be the very last argument on that line, not all the arguments.
$ mkdir -p MyNewInstaller/payload $ cd !$ cd MyNewInstaller/payload
$ touch postinstall $ chmod +x !$ chmod +x postinstall
$ pkgbuild --component /Volumes/Firefox/Firefox.app --install-location /Applications Firefox-51.0.1.pkg $ cp !$ /Volumes/SoftwareArchive/Mozilla/ cp Firefox-51.0.1.pkg /Volumes/SoftwareArchive/Mozilla/
pkgbuild examples are easily dated with the Firefox version.)
If the last command had no arguments,
!$ will be the ‘zeroth’ argument, the command itself:
$ sw_vers ProductName: Mac OS X ProductVersion: 10.12.3 BuildVersion: 16D32 $ !$ sw_vers ProductName: Mac OS X ProductVersion: 10.12.3 BuildVersion: 16D32
There are more
bash history substitutions. I found a helpful StackOverflow post with examples here. Most are a bit too cumbersome to actually use the frequently.
Though, I myself had a ‘lucky ten thousand’ moment, since I did not know about
!* (all the previous command’s arguments) and
!^ (the previous command’s first argument) until today.
Path Through History
This is not directly related to the shell history, but `cd` also remembers your previous location in the file system and you can quickly jump back with `cd -`.
$ cd ~/Projects $ cd ~/Library/AutoPkg/ $ cd - /Users/armin/Projects $ pwd /Users/armin/Projects
- hit ctrl-R and type some text, to get the first command in your history containing that text ↩
- If you do not recognise that reference, you are one the ten thousand, again. ↩
- Yes, technically,
sudo !![return]is the same number of keystrokes as up-arrow, ctrl-a and
sudo[space][return]but I still find it easier. ↩