LFCS Part 48: Working with Command History

Master the Linux command history system to recall, search, and reuse previous commands efficiently for maximum productivity

20 min read

Introduction

Have you ever needed to re-run a complex command you typed earlier, but couldn't remember it exactly? Or wanted to find that one command from yesterday that solved a specific problem? That's where command history comes in.

Linux bash shell keeps a record of every command you type, allowing you to recall, search, edit, and reuse them. This is one of the most powerful productivity features in the terminal. Instead of retyping long commands or complex pipelines, you can simply recall them from history with a few keystrokes.

In this comprehensive guide, you'll learn everything about bash command history. By the end, you'll be able to navigate your command history efficiently, use powerful search features, execute previous commands with shortcuts, and configure history to suit your workflow.

What is Command History?

Command history is bash's built-in feature that remembers the commands you type. Every time you execute a command, bash:

  1. Stores it in memory
  2. Adds it to a history file when you log out (or explicitly save it)
  3. Makes it available for recall and reuse

This history persists across sessions, so commands from weeks or months ago can still be accessed.

The .bash_history File

Bash stores your command history in a file called .bash_history in your home directory.

Location: ~/.bash_history

View it:

ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 24109 Dec 11 16:30 .bash_history

Notice the permissions: rw------- (600) - only you can read and write it. This is important for security since your history might contain sensitive information.

View the contents:

cat ~/.bash_history | head -10
ls
cd /etc
grep root /etc/passwd
sudo systemctl status sshd
ps aux | grep httpd
df -h
free -m
top
history
exit

When Is History Written to the File?

By default, bash writes command history to .bash_history when you:

  1. Log out normally (exit the shell)
  2. Explicitly save it with history -w

Important: Commands from your current session are stored in memory and won't appear in .bash_history until you log out or manually save them.

The history Command

The history command displays your command history with line numbers.

Basic usage:

history
    1  ls
    2  cd /etc
    3  grep root /etc/passwd
    4  sudo systemctl status sshd
    5  ps aux | grep httpd
    ...
 1025  history

Each command has a number that you can use to reference and re-execute it.

Show Last N Commands

Show only the last 10 commands:

history | tail -10
 1016  cat .bash_history | wc -l
 1017  last | tail
 1018  history -w
 1019  ls -l .bash_history
 1020  history | tail
 1021  history -d 1025
 1022  history | tail
 1023  ls -l .bash_history
 1024  cat .bash_history | wc -l
 1025  history | tail

Or use history's built-in option:

history 10

Search History

Find all commands containing a specific word:

history | grep ssh
   42  systemctl status sshd
   87  ps aux | grep ssh
  234  ssh user@192.168.1.100
  456  sudo systemctl restart sshd
 1001  ps aux | tee processes.txt | grep ssh

Understanding HISTSIZE and HISTFILESIZE

Two important environment variables control history behavior:

HISTSIZE

HISTSIZE controls how many commands are kept in memory during your current session.

Check it:

echo $HISTSIZE
1000

Default: Usually 1000 commands

What it means: Bash will remember up to 1000 commands in your current session. When you exceed this limit, the oldest commands are removed from memory.

HISTFILESIZE

HISTFILESIZE controls how many commands are stored in the .bash_history file.

Check it:

echo $HISTFILESIZE
1000

Default: Usually 1000 commands

What it means: The .bash_history file will store up to 1000 commands. When this limit is reached, the oldest commands are removed from the file.

Check Current History Count

cat ~/.bash_history | wc -l
1000

If you see exactly 1000, you've hit the limit. Older commands have been deleted.

Why the Default is 1000

The default of 1000 commands is a balance between:

  • Usefulness: Enough history to recall recent commands
  • Disk space: Doesn't consume too much space
  • Security: Limits exposure if history contains sensitive data
  • Performance: Keeps history searches fast

For most users, 1000 is sufficient. System administrators often increase it to 10,000 or more.

Configuring History Size

You can customize both HISTSIZE and HISTFILESIZE in your ~/.bashrc file.

Increase History Size

Edit ~/.bashrc:

nano ~/.bashrc

Add or modify these lines:

# Increase command history
HISTSIZE=10000
HISTFILESIZE=10000

Save and apply:

source ~/.bashrc

Verify:

echo $HISTSIZE
10000
echo $HISTFILESIZE
10000

Make History Unlimited

For unlimited history (use with caution):

HISTSIZE=-1
HISTFILESIZE=-1

This will never delete old commands, but your history file will grow indefinitely.

history Command Options

The history command has several useful options.

history -c: Clear History

Clear all history from the current session (in memory):

history -c

After this, history shows nothing:

history
    1  history

Note: This only clears memory. It doesn't delete .bash_history until you log out.

history -w: Write History to File

Immediately save current session history to .bash_history:

history -w

Use case: Save important commands before logging out or before clearing history.

Example:

# Check file size before
ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 24109 Dec 11 16:30 .bash_history

# Write current history
history -w

# Check file size after (it updated)
ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 27196 Dec 11 16:35 .bash_history

history -d: Delete Specific Entry

Delete a specific command from history by its number:

history | tail -5
 1021  ls
 1022  cd /etc
 1023  cat /etc/passwd
 1024  rm sensitive_file.txt
 1025  history | tail -5

# Delete command 1024
history -d 1024

# Verify it's gone
history | tail -5
 1021  ls
 1022  cd /etc
 1023  cat /etc/passwd
 1024  history | tail -5
 1025  history | tail -5

Use case: Remove sensitive commands (passwords, API keys, etc.) from history.

history -a: Append New Commands to File

Append commands from current session to .bash_history without overwriting:

history -a

This is useful when running multiple bash sessions simultaneously.

history -r: Read History from File

Read .bash_history into current session's memory:

history -r

Use this to reload history after making manual changes to .bash_history.

Executing Commands from History

Instead of retyping commands, you can execute them directly from history using several shortcuts.

Using !! - Repeat Last Command

!! repeats the last command you ran.

Example:

apt update
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)

# Oops, forgot sudo. Use !! to repeat:
sudo !!
sudo apt update
[sudo] password for user:
...

What happened: !! was replaced with apt update, so the full command became sudo apt update.

Using !n - Execute Command by Number

Execute a command by its history number:

Example:

history | grep ssh
  234  ssh user@192.168.1.100
  456  sudo systemctl restart sshd
  789  ps aux | grep ssh

# Execute command 234
!234
ssh user@192.168.1.100

Using !string - Execute Last Command Starting with String

Execute the most recent command that starts with a specific string:

Example:

history | tail -5
 1020  ls -la /var/log
 1021  cat /etc/hosts
 1022  grep root /etc/passwd
 1023  systemctl status sshd
 1024  history | tail -5

# Execute last command starting with "ls"
!ls
ls -la /var/log
drwxr-xr-x. 12 root root  4096 Dec 11 16:40 .
drwxr-xr-x. 20 root root   278 Nov  3 13:53 ..
...

Another example:

!sys
systemctl status sshd
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
   Active: active (running)

Using !?string - Execute Last Command Containing String

Execute the most recent command that contains a specific string (anywhere in the command):

Example:

history | tail -5
 1020  ls -la /var/log
 1021  cat /etc/hosts
 1022  grep root /etc/passwd
 1023  ps aux | grep httpd
 1024  history | tail -5

# Execute last command containing "httpd"
!?httpd
ps aux | grep httpd

Using !$ - Last Argument of Previous Command

!$ represents the last argument from the previous command.

Example:

cat /etc/ssh/sshd_config
...
(long output)

# Open the same file in an editor:
vim !$
vim /etc/ssh/sshd_config

Another practical example:

mkdir /tmp/my_new_directory

cd !$
cd /tmp/my_new_directory

This saves you from retyping long paths or filenames.

Using !* - All Arguments of Previous Command

!* represents all arguments from the previous command.

Example:

ls -la /etc /var /usr

# Copy all those directories:
cp -r !* /backup/
cp -r /etc /var /usr /backup/

The most powerful history feature is reverse search with Ctrl-R.

How Reverse Search Works

  1. Press Ctrl-R
  2. Start typing part of a command
  3. Bash searches backward through history
  4. Press Enter to execute, or Ctrl-R again to find the next match

Example:

Press Ctrl-R:

(reverse-i-search)`':

Type "ssh":

(reverse-i-search)`ssh': ssh user@192.168.1.100

Bash found the most recent command containing "ssh".

  • Press Enter: Execute it
  • Press Ctrl-R again: Find previous match
  • Press Ctrl-G or Esc: Cancel search
  • Left/Right arrow: Edit the command before executing

Practical Reverse Search Examples

Example 1: Find a complex pipeline:

# Press Ctrl-R and type "grep"
(reverse-i-search)`grep': ps aux | grep httpd | grep -v grep | awk '{print $2}'

Example 2: Find a command with specific arguments:

# Press Ctrl-R and type "ssh 192"
(reverse-i-search)`ssh 192': ssh -i ~/.ssh/mykey.pem user@192.168.1.50

Example 3: Navigate through multiple matches:

# Press Ctrl-R, type "systemctl"
(reverse-i-search)`systemctl': systemctl restart nginx

# Press Ctrl-R again for previous match
(reverse-i-search)`systemctl': systemctl status sshd

# Press Ctrl-R again
(reverse-i-search)`systemctl': systemctl enable httpd

The simplest way to navigate history:

Up Arrow (↑)

  • Shows the previous command
  • Press multiple times to go further back

Down Arrow (↓)

  • Shows the next command (toward more recent)
  • Returns to current prompt when you reach the end

Example:

# Current prompt
[user@host ~]$

# Press ↑ once
[user@host ~]$ history | tail

# Press ↑ again
[user@host ~]$ ls -la /var/log

# Press ↑ again
[user@host ~]$ systemctl status sshd

# Press ↓ to go forward
[user@host ~]$ ls -la /var/log

# Press ↓ again
[user@host ~]$ history | tail

# Press ↓ again (back to prompt)
[user@host ~]$

Additional History Features

HISTCONTROL: Control What Gets Saved

The HISTCONTROL variable controls which commands are saved to history.

Check current setting:

echo $HISTCONTROL
ignoredups:ignorespace

Common values:

| Value | Effect | |-------|--------| | ignoredups | Don't save duplicate consecutive commands | | ignorespace | Don't save commands starting with a space | | ignoreboth | Combine ignoredups and ignorespace | | erasedups | Remove all previous matching commands from history |

Prevent Commands from Being Saved

Method 1: Start command with a space (if ignorespace is set):

echo $HISTCONTROL
ignoreboth

# This won't be saved (note the leading space):
 mysql -u root -p MySecretPassword

Method 2: Clear history after running sensitive command:

mysql -u root -p MySecretPassword
history -d $(history | tail -1 | awk '{print $1}')

Set HISTCONTROL in .bashrc

# In ~/.bashrc
export HISTCONTROL=ignoreboth:erasedups

HISTIGNORE: Ignore Specific Commands

Tell bash to never save certain commands:

# In ~/.bashrc
export HISTIGNORE="ls:pwd:exit:clear:history"

Now ls, pwd, exit, clear, and history won't be saved.

Real-World History Use Cases

Use Case 1: Rerun Complex Commands

You ran a complex pipeline an hour ago:

find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;

To run it again:

# Method 1: Search
Ctrl-R, type "find /var"

# Method 2: History grep
history | grep "find /var"
  543  find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;

!543

Use Case 2: Build on Previous Commands

ls /etc/ssh/
sshd_config  ssh_config  ...

cat !$/sshd_config
cat /etc/ssh/sshd_config

vim !$
vim /etc/ssh/sshd_config

Use Case 3: Fix Typos Quickly

systenctl status sshd
bash: systenctl: command not found...

# Use !! with string replacement
^systenctl^systemctl
systemctl status sshd

The ^old^new syntax replaces old with new in the previous command.

Use Case 4: Document Your Work

# After solving a problem, review what you did:
history | tail -20 > solution_steps.txt

Use Case 5: Audit Activity

Check what commands were run:

# By current user
cat ~/.bash_history

# System-wide (if you have access)
for user in /home/*; do
    echo "=== $user ==="
    sudo cat $user/.bash_history | tail -10
done

Best Practices for Command History

1. Increase History Size

For system administrators:

# In ~/.bashrc
HISTSIZE=10000
HISTFILESIZE=10000

2. Add Timestamps to History

See when commands were run:

# In ~/.bashrc
export HISTTIMEFORMAT="%F %T "

Now history shows timestamps:

history | tail -3
 1023  2025-12-11 16:45:32 ls -la
 1024  2025-12-11 16:46:15 systemctl status sshd
 1025  2025-12-11 16:47:03 history | tail -3

3. Sync History Across Multiple Sessions

If you use multiple terminals:

# In ~/.bashrc
shopt -s histappend
export PROMPT_COMMAND="history -a; history -r"

This appends and reads history after each command.

4. Don't Store Sensitive Commands

Use a leading space or delete them:

#  mysql -u root -pMyPassword  # Leading space - won't be saved
# OR
mysql -u root -pMyPassword
history -d $(history | tail -1 | awk '{print $1}')

5. Regularly Review and Clean History

# Find and remove sensitive patterns
history | grep -i password
history -d <number>

# Or edit .bash_history directly
vim ~/.bash_history

6. Backup Important History

cp ~/.bash_history ~/.bash_history.backup.$(date +%Y%m%d)

Common Pitfalls and How to Avoid Them

Pitfall 1: History Not Saving

Problem: Commands disappear after logout.

Cause: Shell crashed or history -c was run.

Solution: Use history -w to save explicitly before risky operations.

Pitfall 2: Multiple Sessions Overwriting History

Problem: Only the last session's history is saved.

Cause: Each session overwrites .bash_history on exit.

Solution: Set histappend:

shopt -s histappend

Pitfall 3: Can't Find Recent Command

Problem: Recent commands not showing in history.

Cause: They're in memory, not in .bash_history yet.

Solution: Use history command (shows memory) instead of cat ~/.bash_history.

Pitfall 4: Accidentally Executing Wrong Command

Problem: !sys executed the wrong command.

Solution: Preview first:

# In ~/.bashrc
shopt -s histverify

Now !sys will show the command for you to review before executing.

Pitfall 5: Sensitive Data in History

Problem: Passwords or keys stored in history.

Solution: Use HISTIGNORE or leading spaces, and regularly audit:

history | grep -i "password\|secret\|key"

History Command Cheat Sheet

| Command/Shortcut | Description | Example | |-----------------|-------------|---------| | history | Show all history | history | | history 10 | Show last 10 commands | history 10 | | history \| grep term | Search history | history \| grep ssh | | history -c | Clear history (memory only) | history -c | | history -w | Write history to file | history -w | | history -d N | Delete entry number N | history -d 1024 | | history -a | Append new commands to file | history -a | | history -r | Read history from file | history -r | | !! | Repeat last command | sudo !! | | !n | Execute command number n | !234 | | !string | Execute last command starting with string | !ssh | | !?string | Execute last command containing string | !?httpd | | !$ | Last argument of previous command | vim !$ | | !* | All arguments of previous command | cp -r !* /backup/ | | ^old^new | Replace old with new in previous command | ^tset^test | | Ctrl-R | Reverse search history | Press Ctrl-R, type search term | | Ctrl-R again | Find next match in reverse search | While in reverse search | | Ctrl-G | Cancel reverse search | While in reverse search | | (Up arrow) | Previous command | Press ↑ | | (Down arrow) | Next command | Press ↓ |

Environment Variables Cheat Sheet

| Variable | Description | Default | |----------|-------------|---------| | HISTSIZE | Commands kept in memory | 1000 | | HISTFILESIZE | Commands stored in file | 1000 | | HISTFILE | History file location | ~/.bash_history | | HISTCONTROL | What to ignore | ignoredups | | HISTIGNORE | Commands to never save | (none) | | HISTTIMEFORMAT | Timestamp format | (none) |

Practice Labs

Let's practice working with command history.

Lab 1: View Your History

Task: Display all your command history.

Solution
history

Lab 2: Count Your History

Task: Count how many commands are in your current history.

Solution
history | wc -l

Lab 3: View Last 5 Commands

Task: Show only the last 5 commands from your history.

Solution
history | tail -5
# Or:
history 5

Lab 4: Search for Specific Commands

Task: Find all commands in your history that contain the word "systemctl".

Solution
history | grep systemctl

Lab 5: Check History Settings

Task: Display the current values of HISTSIZE and HISTFILESIZE.

Solution
echo $HISTSIZE
echo $HISTFILESIZE

Lab 6: Check History File Size

Task: Count how many lines are in your .bash_history file.

Solution
wc -l ~/.bash_history
# Or:
cat ~/.bash_history | wc -l

Lab 7: Save History Immediately

Task: Write your current session's history to the .bash_history file.

Solution
history -w

Lab 8: Repeat Last Command

Task: Run any command, then repeat it using !!.

Solution
ls -la
!!

Lab 9: Use Last Argument

Task: Create a file, then immediately view it using !$.

Solution
touch /tmp/test_file.txt
cat !$

The !$ expands to /tmp/test_file.txt.

Lab 10: Execute Command by Number

Task: Use history to find a command number, then execute that command using !n.

Solution
history | tail -10
 1015  ls -la
 1016  cd /tmp
 1017  pwd
 ...

# Execute command 1015
!1015
ls -la

Lab 11: Execute Last Command Starting with String

Task: Execute the most recent command that starts with "ls".

Solution
!ls

Lab 12: Delete a History Entry

Task: View your history, pick a command number, and delete it.

Solution
history | tail -10
 1020  ls
 1021  pwd
 1022  whoami
 ...

# Delete command 1021
history -d 1021

# Verify it's gone
history | tail -10

Task: Use Ctrl-R to search for a previous command containing "grep".

Solution
  1. Press Ctrl-R
  2. Type "grep"
  3. Bash shows: (reverse-i-search)grep': history | grep systemctl`
  4. Press Enter to execute, or Ctrl-R again for next match

Lab 14: Use Arrow Keys

Task: Use the up arrow to navigate to a previous command, edit it, and run it.

Solution
  1. Press ↑ (up arrow) one or more times
  2. Use left/right arrows to position cursor
  3. Edit the command
  4. Press Enter to execute

Lab 15: Increase History Size

Task: Temporarily set HISTSIZE to 5000 for your current session.

Solution
export HISTSIZE=5000

# Verify
echo $HISTSIZE
5000

Note: This is temporary. To make it permanent, add to ~/.bashrc.

Lab 16: Add Timestamps to History

Task: Enable timestamps for history in your current session.

Solution
export HISTTIMEFORMAT="%F %T "

# Verify
history | tail -3
 1023  2025-12-11 17:15:42 ls -la
 1024  2025-12-11 17:16:05 pwd
 1025  2025-12-11 17:16:20 history | tail -3

Lab 17: Clear History

Task: Clear all command history from your current session (be careful!).

Solution
history -c

# Verify
history
    1  history

Note: This only clears memory. The .bash_history file is unchanged until logout.

Lab 18: Backup Your History

Task: Create a backup copy of your .bash_history file with today's date.

Solution
cp ~/.bash_history ~/.bash_history.backup.$(date +%Y%m%d)

# Verify
ls -l ~/.bash_history*

Lab 19: Find Commands from Today

Task: If you have HISTTIMEFORMAT enabled, find all commands you ran today.

Solution
# First enable timestamps if not already:
export HISTTIMEFORMAT="%F %T "

# Then search for today's date
history | grep "$(date +%F)"

Lab 20: Prevent Command from Being Saved

Task: Run a command with a leading space so it won't be saved to history (requires HISTCONTROL=ignorespace or ignoreboth).

Solution
# Check if ignorespace is set
echo $HISTCONTROL
ignoreboth

# Run command with leading space (note the space before echo):
 echo "This won't be in history"

# Verify it's not in history
history | tail -5
# (The echo command should not appear)

Key Takeaways

  1. Command History Saves Commands: Bash remembers every command you type

  2. Storage Locations:

    • Memory: Current session (controlled by HISTSIZE)
    • File: ~/.bash_history (controlled by HISTFILESIZE)
  3. Default Limit: 1000 commands (can be increased)

  4. The history Command:

    • history - show all history
    • history -c - clear history (memory)
    • history -w - write to file immediately
    • history -d N - delete entry number N
  5. Execution Shortcuts:

    • !! - repeat last command
    • !n - execute command number n
    • !string - execute last command starting with string
    • !$ - last argument of previous command
  6. Reverse Search: Ctrl-R is the most powerful search feature

  7. Arrow Keys: Use ↑ and ↓ to navigate history

  8. Configuration: Customize in ~/.bashrc:

    • Increase HISTSIZE and HISTFILESIZE
    • Add HISTTIMEFORMAT for timestamps
    • Set HISTCONTROL to control what's saved
  9. Security: Be careful with sensitive data in history

  10. Productivity: Mastering history saves enormous time and effort

What's Next?

You now understand how to leverage bash command history for maximum productivity. In the next post, Part 49: Command Line Completion and bash-completion, we'll learn how to:

  • Use Tab completion for commands, files, and directories
  • Understand single vs double Tab press
  • Install and configure bash-completion package
  • Get intelligent completion for specific commands
  • Create custom completion scripts
  • Speed up your command-line workflow even more

Tab completion is another essential productivity feature that, combined with command history, makes you incredibly efficient in the terminal. See you in the next post!

Thank you for reading!

Published on January 8, 2026

Owais

Written by Owais

I'm an AIOps Engineer with a passion for AI, Operating Systems, Cloud, and Security—sharing insights that matter in today's tech world.

I completed the UK's Eduqual Level 6 Diploma in AIOps from Al Nafi International College, a globally recognized program that's changing careers worldwide. This diploma is:

  • ✅ Available online in 17+ languages
  • ✅ Includes free student visa guidance for Master's programs in Computer Science fields across the UK, USA, Canada, and more
  • ✅ Comes with job placement support and a 90-day success plan once you land a role
  • ✅ Offers a 1-year internship experience letter while you study—all with no hidden costs

It's not just a diploma—it's a career accelerator.

👉 Start your journey today with a 7-day free trial

Related Articles

Continue exploring with these handpicked articles that complement what you just read

45 min read

LFCS Part 52: Bash Startup Files and Configuration (FINAL POST!)

Master bash startup and configuration files. Learn the difference between login and non-login shells, understand /etc/profile, ~/.bashrc, ~/.bash_profile, and when to modify each file. Complete guide with practical examples and 20 hands-on labs for LFCS certification preparation.

#linux#lfcs+6 more
Read article

More Reading

One more article you might find interesting