Shell history expansion: a guide to lazy command reuse with exclamation marks
Tutorial on using bash/zsh event designators to avoid repeating commands and arguments.
Conversation activity · last 3 days peak 5/hr
Summary, timeline and people extracted by Claude from 55 items across 3 sources · 8h ago. Quotes are verbatim.
A technical article published on Lobsters explains how to use shell history expansion (exclamation mark syntax) to reuse previous commands and their arguments, promoting the DRY principle on the command line. The post sparked discussion about trade-offs between this feature and alternative shells like fish and nushell, with commenters debating usability, safety, and shell choice.
- Shell history expansion using event designators (e.g. !!, !$, !ssh) allows reuse of previous commands and arguments, applying DRY principle to command-line work.
- Practical concerns exist: commands expand invisibly before execution, creating safety risks for destructive operations like find or rm.
- Alternative shells (fish, nushell) offer superior UX through auto-completion and explicit command editing, though bash/zsh remain preferred for legacy system compatibility and established workflows.
How it unfolded
-
Reaction Bash defense offered
Commenter wwfn argues bash deserves credit as a pleasant, sufficient tool with good ecosystem support like shellcheck.
-
Reaction Alternative shells debate
Commenter nicoco questions why developers use bash/zsh instead of more user-friendly alternatives, with responses discussing legacy system constraints and muscle memory.
-
Reaction zsh history expansion behavior clarified
Commenter leela shows that zsh stores expanded command versions in history, addressing one potential gotcha of the feature.
-
Reaction Safety concerns raised
Commenter spookylukey argues that editing commands interactively is safer than blind history expansion, citing destructive command examples.
-
Reaction Fish shell alternative mentioned
Commenter symgryph argues that fish shell eliminates the need for history expansion complexity through superior auto-completion.
-
Reaction zsh tab-expansion capabilities noted
Commenter banna demonstrates that zsh can expand event designators with tab completion, showing practical usability improvement.
-
Report Article published on Lobsters
User seb posts article titled 'A shell exclamation mark is not for yelling. Be lazy' explaining event designators and history expansion syntax in bash, csh, tcsh, and zsh.
What people are saying verbatim
“I know I might go to posix hell for this but I just use fish shell and I don't have to worry about all that nonsense. It just Auto completes nicely.”
symgryph, Lobsters commenter · Lobsters · Aug 7, 1:45 AM
“The problem with `!` is that— AFAIK— you can't see the expansion before running it.”
quad, Lobsters commenter · Lobsters · Aug 7, 7:30 AM
“Honestly, being able to quickly find and edit a previous line feels so much better than this for most cases, especially for commands that can be destructive.”
spookylukey, Lobsters commenter · Lobsters · Aug 7, 2:02 AM
“It is mindboggling to me that so many people use bash or zsh and not the user-friendlier alternatives like fish, nushell and other.”
nicoco, Lobsters commenter · Lobsters · Aug 7, 7:53 AM
“shell is the right tool for some programs and bash is more than just the sufficient almost-always-installed default, it's pleasant to work with once familiar!”
wwfn, Lobsters commenter · Lobsters · Aug 7, 10:31 AM
Voices from the web unedited
-
I know I might go to posix hell for this but I just use fish shell and I don't have to worry about all that nonsense. It just Auto completes nicely. I kind of take it for granted.
-
you could also do: $ build-command $ run-command $ && cuts from cursor to beginning, and pastes.
-
At least in zsh, the history only stores the expanded versions: ```shell % echo 'hello world' hello world % !:s/world/lobsters echo 'hello lobsters' hello lobsters % history ... 10052 echo 'hello world' 10053 echo 'hello lobsters' ```
-
It is mindboggling to me that so many people use bash or zsh and not the user-friendlier alternatives like fish, nushell and other. The arguments I hear against switching from the default usually fall into two categories: - (online) I need to use legacy systems where only (ba)sh is available and I'm not root, it's just easier to always use this…
-
I tried fish and sure it's obviously nicer than bash. I bounced off it because the syntaxes for things like for loops and variable assignments are quite different from sh and it was fighting my muscle memory.
-
The problem with `!` is that— AFAIK— you can't see the expansion before running it.
-
I don't like using these: they litter your history with history-dependent commands
-
Honestly, being able to quickly find and edit a previous line feels so much better than this for most cases, especially for commands that can be destructive - which is a large fraction of shell commands. As an example, I recently got bitten by the gotchas below: ``` find . -name '*~' find . -name '*~' -print0 find . -name '*~' -o -name '*.bak'…
-
`zsh` handles tab-expansion for event designators to some degree… ``` $ zsh --version zsh 5.9 (arm64-apple-darwin25.0) $ ls ~/some/path ls: /some/path: No such file or directory $ mkdir !:$ # will expand to ~/some/path in the readline $ !z # again will expand to the most recent closest-match, i.e. 'zsh --version' ```
-
It is a hack, but I recently discovered ctrl+o in Bash (or I guess most readline stuff). After you recall a command from history (with ctrl+r, for example), ctrl+o executes it and moves to the next command in the history.