Bash Shell: Reusing parts of previous commands
I’ve paired a few times with my colleague Phil Potter over the last couple of weeks and since he’s a bit of a ninja with bash shortcuts/commands I wanted to record some of the things he’s shown me so I won’t forget them!
Let’s say we’re in the '/tmp' directory and want to create a folder a few levels down but forget to pass the '-p' option to 'mkdir':
$ mkdir blah/de/blah
mkdir: cannot create directory `blah/de/blah': No such file or directory
One way of fixing that would be to press the up arrow and navigate along the previous command and put in the '-p' flag but it’s a bit fiddly so instead we can do the following:
$ ^mkdir^mkdir -p
mkdir -p blah/de/blah
The '^' allows us to replace any parts of the previous command and then run it again, so we could actually make that more concise if we wanted to:
$ ^r^r -p
mkdir -p blah/de/blah
Reasonably frequently after we’ve created a folder like this we’ll want to create a file inside it. '!$' comes in handy here as it allows us to refer to the last argument passed to the last command:
$ touch !$/blah.xml
touch blah/de/blah/blah.xml
If we decide to remove that file and want to check it’s been deleted we can run the following:
$ touch blah/de/blah/blah.xml
$ rm blah/de/blah/blah.xml
$ ls -alh !$:h
ls -alh blah/de/blah
total 8.0K
drwxr-xr-x 2 mneedham mneedham 4.0K 2012-07-05 16:26 .
drwxr-xr-x 3 mneedham mneedham 4.0K 2012-07-05 16:16 ..
The ':h' modifier removes the file name and leaves the rest of the file path alone.
We can expand the value of '!$' or any other command by typing 'Esc' followed by '^' (Shift 6):
mneedham@ubuntu:/tmp$ mkdir -p blah/de/blah
mneedham@ubuntu:/tmp$ touch !$
Esc + ^
$ mkdir -p blah/de/blah
$ touch blah/de/blah
If we get carried away with modifiers we could also fix that first 'mkdir' command by making use of the 'substitution' modifier:
$ mkdir blah/de/blah
mkdir: cannot create directory `blah/de/blah': No such file or directory
$ !!:s/r/r -p
mkdir -p blah/de/blah
There’s not really any reason I can think of why you’d want to use that when you can use the initial '^' approach though!
I came across this blog post which explains how to do this type of thing and much more in the bash shell - worth a read!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.