Interesting and useful use cases of !, #, and ? expansions in Bash
I love to always learn new Linux shell commands and wrangling moves. This recent days I learned a few useful command line “tricks” that I’ve never seen anyone using so I thought of sharing them.
They all cover the special characters and escape sequences related to history expansion and prompt customization. This post will:
- Clarify the real tools behind
!,#, and?in Bash. - Walk through practical examples you can copy and adapt.
- Challenge assumptions by revealing lesser-known tricks.
- Deliver actionable steps to integrate these shortcuts into your workflow.
[!INFO] Some of this “chops” are not as intuitive so I guess it’s a matter of practicing a few at a time so eventually they become second nature. I’ve found that when we’re working on the command line, we do sub-second operations that rely 100% on muscle memory and intuition, so it’s useful to learn this “tricks” before we ever need them so they’re there in our memory when we actually do.
Bash History Expansion (!)
#
Bash’s history expansion allows you to recall and re-execute commands from your session’s history.
!!— Repeat the entire last command.
This may be the most commonly needed one: when we forgot to use sudo and need to run our command again…
$ sudo !! # run the previous command with sudo
-
!n— Execute command number n fromhistory.$ history # get list 42 ls 43 pwd 44 echo hello $ !43 # runs `pwd` -
!-n— Run the command n lines back.$ !-2 # repeat the command two steps ago -
!string— Execute the most recent command starting withstring.$ !ec # runs `echo hello` if that was the last matching -
!?string?— Execute the most recent command containingstring.$ history 50 ls /var/log 51 cat /var/log/syslog 52 echo done $ !?syslog? # runs `cat /var/log/syslog` -
Word designators — Extract portions of the previous command:
!:0— The command itself (e.g.cat).!:1— First argument (e.g./var/log/syslog).!:n— nth argument.!$— Last argument (same as!: -1).!^— First argument (!:1).!mkdir:$— “Fetch” lastmkdircommand in our history, and “reuse” its argument (See example below)
For example, having written a command with a large argument, and wanting to reuse it with other command:
- Here, we “reuse” mkdir argument, which we don’t want to write again, and just append “README.md” to create a file there:
Since we cannot simply use !$ because mkdir is not our last command anymore, we can “fetch” it from our history and “reuse” its argument:
That’s it for this quick recap. Those new “chops” are very useful for those long work sessions on the terminal and can save us some precious time with tedious commands.