Bash History Expansion: Speed Up Your Command Line

Bash history expansion is a powerful feature that lets you quickly reference and re-execute previous commands without retyping them. Once you master these tricks, you’ll significantly speed up your command-line workflow.

Quick Reference

Expansion What It Does Example
!! Repeat the last command sudo !!
!-n Go back n commands !-2 (2 commands ago)
!494 Run command #494 from history !494
!$ Last argument of previous command cd !$
!^ First argument of previous command rm !^

Understanding Bash History

View Your History

To see your recent commands, use:

$ history 5
  501  echo "Building the project..."
  502  npm run build
  503  ls -la dist/
  504  cat README.md
  505  echo "Done!"

This prints the last 5 commands from your bash history. Each command is numbered, which you can use for direct access. Notice that command 502 is the npm run build command—you can reference it directly using !502.

Re-executing Commands

The Essential: Repeat the Last Command with !!

The Most Used Expansion
!! repeats the last command you executed. It’s the simplest and most useful bash history expansion.

The !! is actually just an shortcut for !-1, which means the last command in my history. But !! is shorter and more idiomatic.

sudo !! is probably the most useful history expansion you’ll use. It automatically prepends sudo to your last command when you forget elevated privileges.

$ systemctl restart nginx
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to get D-Bus connection: Operation not permitted
$ sudo !!
sudo systemctl restart nginx
nginx restarted successfully

This saves you from retyping the entire command and is one of the most valuable history expansions in daily use.

Going Back: Relative Position with !-n

You can use negative position to count back from your current command. For example:

$ history 10
  496  touch notes.txt
  497  echo "Project setup" >> notes.txt
  498  cat notes.txt
  499  ls -la
  500  touch deploy.sh
  501  echo "Building..." >> notes.txt
  502  npm run build
  503  ls dist/
  504  cat package.json
  505  echo "Complete"
$ !-4
npm run build
> my-app@1.0.0 build
> webpack --mode production
webpack 5.89.0 compiled successfully in 2.3s

Direct Access: Run Command by Number with !n

You can run any command from your history by its number. First, check your history to find the number:

$ history 10
  496  touch notes.txt
  497  echo "Project setup" >> notes.txt
  498  cat notes.txt
  499  ls -la
  500  touch deploy.sh
  501  echo "Building..." >> notes.txt
  502  npm run build
  503  ls dist/
  504  cat package.json
  505  echo "Complete"
$ !502
npm run build
> my-app@1.0.0 build
> webpack --mode production
webpack 5.89.0 compiled successfully in 2.3s

Now command 502 is re-executed without having to retype it.


Reusing Arguments

Last Argument: !$

Saves Typing Long Paths
The !$ expansion gives you the last argument from the previous command. Perfect when you have long file paths or complex arguments to reuse.
$ mkdir my_new_project
$ cd !$
cd my_new_project
$ pwd
/home/user/my_new_project

This is especially useful when you have long file paths or complex arguments. Here’s a more realistic example:

$ touch /home/user/documents/projects/webapp/config-production.json
$ cat !$
cat /home/user/documents/projects/webapp/config-production.json
{
  "api": "https://api.example.com",
  "env": "production",
  "debug": false
}

Instead of typing the long path again, !$ automatically expands to the last argument from the previous command.


First Argument: !^

Use !^ to get the first argument from the previous command:

$ cp /very/long/path/file.txt /backup/
$ ls -la !^
ls -la /very/long/path/file.txt
-rw-r--r-- 1 user user 2048 Nov 16 10:23 /very/long/path/file.txt

The !^ expansion pulls just the first argument, so you don’t need to retype long paths when working with the source file.


Why This Matters

These small tricks compound over time. When you’re running dozens of commands per day, eliminating just a few keystrokes per command adds up to significant time savings. Plus, sudo !! is a lifesaver when you forget elevated privileges on the first attempt.

Master these expansions and watch your terminal productivity soar!