You know that moment when you're staring at command line stuff and see something like !-
or !$
? First time I bumped into this exclamation mark on dash thing was during a server migration disaster. I'd copied what looked like a normal command from Stack Overflow, and bam – deleted the wrong directory. Took me three hours to recover. Felt like an idiot. But here's the thing: that little punctuation combo is way more powerful than it looks.
What Exactly Is Exclamation Mark on Dash?
At its core, exclamation mark on dash refers to using !-
in Unix-like shells (Bash, Zsh, etc.). It's not one operator but two separate pieces working together: the history expansion (!
) and the dash modifier (-
). When you mash them together, magic happens.
Remember how Windows makes you click through folders? This is the terminal's power move. Say you run:
cd !-:1
That second line? It's grabbing the first argument (:1
) from your previous command (!
). So instead of typing the whole path again, you jump straight to /long/annoying/path/to/
. Lifesaver when dealing with deep directories.
Where You'll Actually Use This
- Quick directory jumps after moving/copying files
- Reusing parts of long commands without retyping
- Chaining operations when debugging scripts
- Fixing typos in complex arguments (my personal savior)
Last week I saved 15 minutes on a deployment just by using !-2:3
to pull a path from two commands back. Felt like cheating.
Real-World Examples That Don't Suck
Forget textbook examples. Here's how exclamation mark on dash works in actual workflows:
Case 1: The Multi-Step Deployment
npm run build -- --env=production
# Step 2: Move output to server dir (using argument from Step 1)
mv dist/ !-:2
# Step 3: Restart service in that directory
systemctl restart myapp@!-:1.service
See how !-:2
grabs --env=production
? And !-:1
takes dist/
? That's three commands sharing arguments without retyping.
Case 2: The "Oh Crap" Correction
chmod 777 /important/system/config.yaml
# Fix permissions using previous argument:
chmod 600 !-:1
No frantic up-arrow + left-arrow mashing. Just reuse the path immediately.
Exclamation Mark on Dash vs. Other Shortcuts
People confuse this with regular history expansion. Here's the breakdown:
Syntax | What It Does | When It Fails |
---|---|---|
!- |
Arguments from previous command | If previous command has no arguments |
!! |
Repeat entire last command | Destructive commands (rm, shutdown) |
!$ |
Last argument of last command | Only gets one item |
!* |
All arguments of last command | Includes flags/switches |
Pro tip: Combine these like grep error !-:2/!$
to search in the last directory from two commands ago. Yeah, it looks like alphabet soup but saves hours.
echo
first! Running rm -rf !-:1
without checking could nuke the wrong thing. Ask me how I know...
Weird Edge Cases I've Stumbled Into
Not all shells handle exclamation mark on dash the same. Here's where things get messy:
The Zsh Quirk
Zsh requires setopt hist_verify
for safe expansion. Forgot this once during a live demo – expanded a git reset !-:1
and wiped uncommitted changes. Awkward silence.
When Commands Have Flags
Consider:
ls -l !-:1
Here, !-:1
expands to -o
– not what you want! Solution: use !-:2
to skip flags.
Nested Commands Disaster
Never nest exclamation mark on dash like ssh server 'ls !-:1'
. It expands on your local machine before sending. I learned this by exposing my ~/Documents path to a production server. Not ideal.
Handy Reference Cheat Sheet
Bookmark this table:
Shortcut | Example Input | Expands To | Use Case |
---|---|---|---|
!-:n |
ls !-:2 | ls /path/to/file | Get nth argument from last command |
!-^* |
chmod +x !-^* | chmod +x script.sh | All arguments except the first |
!-:x-y |
tar czf !-:2-4 | tar czf file1.txt dir/ config.json | Arguments range |
!-:0 |
sudo !-:0 | sudo apt | Command name only |
FAQs: Stuff People Actually Search
"Why did !- delete my file?"
Probably expanded to something unexpected. Always preview with echo !-
first. History expansion doesn't care about your feelings.
"Is exclamation mark on dash safe for scripts?"
God no. It's interactive-only. Scripts should use $_
or variables. Learned this when cron jobs started failing mysteriously.
"Can I use exclamation mark on dash with sudo?"
Yes but it's tricky. sudo !!
works, but sudo !-:2
expands before sudo. Better to do sudo $(history -p !-)
in Bash.
"Why doesn't !- work in my terminal?"
Check:
- You're in Bash/Zsh (not Fish/sh)
- History is enabled (
set -o history
) - No spaces in
!-
(some setups require! -
)
Pro Tips You Won't Find in Manuals
- Combine with search:
!?find?:2
gets the 2nd argument from last 'find' command - Modify arguments:
vim !-:1:s/.txt/.md/
changes extension - Skip dangerous commands: Add
#danger
after commands you don't want to expand
A colleague showed me this trick for mass renaming:
convert "$f" !-:1:r.png
done
The !-:1:r
grabs the root name of previous argument. Witchcraft.
When to Avoid This Like the Plague
Despite my love for exclamation mark on dash, never use it for:
- Any command involving deletion or formatting
- Scrips running as root (just don't)
- Automated CI/CD pipelines (use variables instead)
- When tired or distracted (trust me)
There's this infamous DevOps horror story where aws s3 rm s3://bucket/ !-:1
during migration expanded to aws s3 rm s3://bucket/ /
. Bye-bye production bucket.
Bottom Line: Should You Bother Learning This?
If you live in terminal:
- Yes for interactive use – saves tons of typing
- No for scripting – too unpredictable
It's one of those things that feels awkward initially. I avoided it for years. But once you build the muscle memory? Honestly can't work without it now. Just treat it like a power tool – respect the danger, but damn it's efficient.
What's your exclamation mark on dash horror story? Mine involved a misused !-
and a production database restore. We don't talk about that Monday.