| |

LFCS 48 ๐Ÿง Shell History โ€” Configuration and Use

โฑ๏ธ Estimated read: 11 min | |

Shell history is the mechanism that records every command you type, lets you recall and re-execute them, and persists them across sessions in a file. For the LFCS exam, this falls under the “Essential Commands” domain and the “User and Group Management” domain, specifically “Manage template user environment” and “Use shell/environment variables” . The history system has two layers: an in-memory list that holds the current session’s commands, and a file (~/.bash_history by default) that persists them across logins. The configuration variables control how many commands are kept, which commands are ignored, and whether timestamps are recorded.

The distinction between the in-memory list and the file is the source of most confusion. history -c clears the memory but does not touch the file. history -w writes the memory to the file immediately. When the shell exits normally, it automatically writes the last $HISTSIZE entries to $HISTFILE . If the shell crashes or the terminal is closed abruptly, the commands from that session may never reach the file. This is why PROMPT_COMMAND="history -a" is a common configuration: it appends each command to the file after it runs, so the history survives a crash .

Key point: The history list is held in memory and written to ~/.bash_history on exit; HISTSIZE controls the in-memory list, HISTFILESIZE controls the file, HISTCONTROL and HISTIGNORE filter what is saved, and history -c, -w, -a, -r, and -d manipulate the list and file explicitly.


Why the history configuration variables matter

The persistence problem. Without HISTFILE, history is lost when the shell exits. The default ~/.bash_history is read at startup and written at exit . The histappend shell option controls whether the shell appends to the file or overwrites it. Without histappend, opening two terminals and closing them in sequence means the second terminal’s history overwrites the first’s. With shopt -s histappend, both sessions append, and the file accumulates all commands .

The size problem. HISTSIZE is the number of commands kept in memory (default 500). HISTFILESIZE is the number of lines kept in the file. If HISTFILESIZE is unset, the file is not truncated . A common production configuration sets both to large values: HISTSIZE=1000000 and HISTFILESIZE=20000000 . The memory cost is negligible, and the benefit is that a long-running session does not lose early commands.

The filtering problem. HISTCONTROL controls what is saved. ignorespace means commands starting with a space are not saved. ignoredups means consecutive duplicates are not saved. ignoreboth combines the two. erasedups removes all previous occurrences of a command before saving the new one . HISTIGNORE is a colon-separated list of patterns. A pattern of history means the history command itself is not saved. A pattern of ?:?? means one- and two-character commands are not saved . These variables are how a user prevents noise from filling the history file.

The timestamp problem. By default, history entries have no timestamps. Setting HISTTIMEFORMAT to a format string like "%F %H:%M:%S " makes the history command display timestamps, and it causes the shell to write timestamp comments to the history file so the times persist across sessions . This is essential for forensic analysisโ€”knowing that a command ran is less useful than knowing when it ran.


a. Configuration in ~/.bashrc

The history configuration belongs in ~/.bashrc, the file read by interactive shells. The settings are environment variables and shell options.

# ~/.bashrc

# Append to history file instead of overwriting it
shopt -s histappend

# Number of commands kept in memory for the current session
HISTSIZE=1000000

# Number of lines kept in the history file
HISTFILESIZE=20000000

# Ignore commands starting with a space, and ignore duplicates
HISTCONTROL=ignoreboth:erasedups

# Do not save one- and two-character commands
HISTIGNORE="?:??"

# Display timestamps in the history output
HISTTIMEFORMAT="%F %H:%M:%S   "

# Save each command to the file immediately after it runs
PROMPT_COMMAND="history -a"

The PROMPT_COMMAND="history -a" line is a reliability improvement. Without it, the history is written to the file only when the shell exits. If the terminal crashes or the session is killed, the commands are lost. With it, each command is appended to the file as soon as it completes . The history -a command appends the new entries from the in-memory list to the file without clearing the list.

The HISTIGNORE pattern ?:?? is a filter for noise. The ? matches one character, and ?? matches two. A command like ls is two characters and is not saved. A command like cd is two characters and is not saved. The colon separates the patterns, and the entire line must match one of the patterns .


b. Recalling and re-executing commands

The history builtin lists the commands with their numbers. The number is the key to re-execution.

# List the most recent 20 commands
history 20

# Re-execute the command at line 42
!42

# Re-execute the last command
!!

# Re-execute the last command that starts with "git"
!git

# Re-execute the command n positions back
!-3

The ! expansion is performed by the shell before the command is executed. !! is the most common shortcut because it re-runs the last command. A classic use is sudo !!, which re-runs the previous command with sudoโ€”useful when you forget the privilege escalation on a command that needs it. The expansion happens before sudo runs, so sudo !! becomes sudo apt update if the previous command was apt update.

The Ctrl+R shortcut starts a reverse incremental search. Typing a substring searches backward through the history and displays the first match. Pressing Ctrl+R again moves to the earlier match. Pressing Enter executes the matched command; pressing Esc or an arrow key places it on the command line without executing . This is the fastest way to find a long command that was run days ago.

The fc builtin is an alternative to history. fc -l lists the history, and fc -s re-executes a command. It is less commonly used than history and !, but it is part of the Bash manual’s documented interface .


c. Clearing and manipulating the history file

The history builtin has flags for manipulating the list and the file. The distinction between them is the source of most mistakes.

# Clear the in-memory history list (does not touch the file)
history -c

# Write the in-memory list to the history file (overwrites)
history -w

# Append new entries from memory to the file
history -a

# Read the file into memory (useful after editing the file)
history -r

# Delete a specific entry by its number
history -d 42

history -c clears the in-memory list but leaves ~/.bash_history untouched. If you clear the memory and then exit the shell normally, the shell writes the (now empty) memory to the file, effectively clearing the file as well. But if the shell crashes before exiting, the file retains the old commands. history -w writes the memory to the file immediately, which is how you force a save without exiting. history -a appends only the new entries, which is what PROMPT_COMMAND uses .

history -d 42 removes the entry at line 42 from the in-memory list. It does not remove it from the file unless you follow it with history -w . To delete a specific line from the file directly, you edit ~/.bash_history and then run history -r to reload the modified file into memory.

For system-wide history configuration, the file is /etc/profile.d/ with a .sh extension. Files there are sourced by /etc/profile for all users. However, history variables are typically per-user preferences, so system-wide settings are less common than per-user settings in ~/.bashrc.


Complete Example Session

The following session configures history settings, demonstrates the difference between memory and file, and uses the recall shortcuts.

# ============================================
# PART 1: CONFIGURE HISTORY IN ~/.bashrc
# ============================================
# Append the settings to .bashrc
cat >> ~/.bashrc << 'EOF'
# Append to the history file instead of overwriting
shopt -s histappend
# Large in-memory and file limits
HISTSIZE=1000000
HISTFILESIZE=20000000
# Ignore space-prefixed and duplicate commands
HISTCONTROL=ignoreboth:erasedups
# Do not save one- and two-character commands
HISTIGNORE="?:??"
# Show timestamps
HISTTIMEFORMAT="%F %H:%M:%S   "
# Save each command immediately
PROMPT_COMMAND="history -a"
EOF

# Reload .bashrc
source ~/.bashrc

# ============================================
# PART 2: DEMONSTRATE HISTCONTROL
# ============================================
# A command with a leading space is not saved
 ls /tmp
# Verify it is not in the history
history | tail -1
# Output: the previous command, not "ls /tmp"

# ============================================
# PART 3: DEMONSTRATE HISTIGNORE
# ============================================
# A two-character command is not saved
cd /tmp
# Verify it is not in the history
history | tail -1
# Output: the previous command, not "cd"

# ============================================
# PART 4: RECALL AND RE-EXECUTE
# ============================================
# Run a command
echo "hello history"

# Re-execute the last command
!!
# Output: hello history

# Re-execute the last command starting with "echo"
!echo
# Output: hello history

# ============================================
# PART 5: CLEAR MEMORY VS FILE
# ============================================
# Clear the in-memory list
history -c

# The file still contains the old commands
tail -3 ~/.bash_history
# Output: the last three commands from the file

# Write the empty memory to the file
history -w

# The file is now empty
wc -l ~/.bash_history
# Output: 0

The five parts cover the configuration, the HISTCONTROL filtering, the HISTIGNORE filtering, the recall shortcuts, and the distinction between clearing memory and clearing the file. What the session demonstrates is that history -c alone does not erase the file, and that the filtering variables prevent noise from being saved in the first place.


Quick Reference

Configuration Variables

VariablePurposeDefault
HISTSIZECommands in memory500
HISTFILESIZELines in file500
HISTFILEHistory file path~/.bash_history
HISTCONTROLFiltering rules(unset)
HISTIGNOREPattern list to ignore(unset)
HISTTIMEFORMATTimestamp display format(unset)

HISTCONTROL Values

ValueEffect
ignorespaceIgnore commands starting with space
ignoredupsIgnore consecutive duplicates
ignorebothBoth of the above
erasedupsRemove all previous duplicates

history Builtin Flags

FlagEffect
-cClear in-memory list
-wWrite memory to file (overwrite)
-aAppend new entries to file
-rRead file into memory
-d nDelete entry n from memory

Recall Shortcuts

ShortcutEffect
!!Re-execute last command
!nRe-execute command n
!stringRe-execute last command starting with string
!-nRe-execute command n positions back
Ctrl+RReverse incremental search

Best Practices

โœ… Do This:

# Append instead of overwrite
shopt -s histappend

# Save immediately to survive crashes
PROMPT_COMMAND="history -a"

# Show timestamps for forensics
HISTTIMEFORMAT="%F %H:%M:%S "

# Filter noise
HISTIGNORE="?:??:history"

โŒ Don’t Do This:

# Rely on history -c alone to erase the file
history -c  # file still contains old commands

# Forget that histappend is off by default
# Two terminals overwrite each other's history

# Set HISTSIZE=0 to disable history silently
# (legitimate, but surprising)

Common Pitfalls

PitfallWhy It HappensFix
History lost on crashWritten only on exitPROMPT_COMMAND="history -a"
Two terminals overwritehistappend not setshopt -s histappend
history -c does not erase fileClears memory onlyFollow with history -w
Duplicates fill historyHISTCONTROL unsetignoredups or erasedups
Timestamps missingHISTTIMEFORMAT unsetSet the variable

Real-World Examples

1. Append mode

shopt -s histappend

2. Immediate save

PROMPT_COMMAND="history -a"

3. Ignore space-prefixed

HISTCONTROL=ignorespace

4. Ignore duplicates

HISTCONTROL=erasedups

5. Ignore common commands

HISTIGNORE="history:exit:clear"

6. Timestamps

HISTTIMEFORMAT="%F %H:%M:%S "

7. Re-run last command

!!

8. Re-run with sudo

sudo !!

9. Clear memory and file

history -c && history -w

10. Delete one entry

history -d 42

Visual

Memory vs File

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SHELL SESSION                               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  In-memory history list                โ”‚  โ”‚
โ”‚  โ”‚  (HISTSIZE)                            โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                   โ”‚                          โ”‚
โ”‚         history -w (write)                   โ”‚
โ”‚         history -a (append)                  โ”‚
โ”‚                   โ”‚                          โ”‚
โ”‚                   โ–ผ                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  ~/.bash_history                       โ”‚  โ”‚
โ”‚  โ”‚  (HISTFILESIZE)                        โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                              โ”‚
โ”‚  history -c โ†’ clears memory only             โ”‚
โ”‚  history -r โ†’ reads file into memory         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Filtering Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Command entered                             โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  HISTCONTROL check                          โ”‚
โ”‚  โ”œโ”€ starts with space? โ†’ skip               โ”‚
โ”‚  โ”œโ”€ consecutive duplicate? โ†’ skip           โ”‚
โ”‚  โ””โ”€ otherwise โ†’ continue                    โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  HISTIGNORE check                           โ”‚
โ”‚  โ”œโ”€ matches pattern? โ†’ skip                 โ”‚
โ”‚  โ””โ”€ otherwise โ†’ save                        โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  Added to history list                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Recall Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  !!                                          โ”‚
โ”‚  โ†’ last command                              โ”‚
โ”‚                                              โ”‚
โ”‚  !42                                         โ”‚
โ”‚  โ†’ command at line 42                        โ”‚
โ”‚                                              โ”‚
โ”‚  !git                                        โ”‚
โ”‚  โ†’ last command starting with "git"          โ”‚
โ”‚                                              โ”‚
โ”‚  Ctrl+R                                      โ”‚
โ”‚  โ†’ incremental reverse search                โ”‚
โ”‚  โ†’ Enter executes, Esc places on line        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Persistence Across Sessions

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Session 1                                   โ”‚
โ”‚  commands โ†’ memory โ†’ exit โ†’ file            โ”‚
โ”‚                                              โ”‚
โ”‚  Session 2                                   โ”‚
โ”‚  file โ†’ memory at startup                    โ”‚
โ”‚  new commands โ†’ memory โ†’ exit โ†’ file        โ”‚
โ”‚                                              โ”‚
โ”‚  Without histappend:                         โ”‚
โ”‚  Session 2 overwrites Session 1's file      โ”‚
โ”‚                                              โ”‚
โ”‚  With histappend:                            โ”‚
โ”‚  Session 2 appends to Session 1's file      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
In-memory sizeHISTSIZE (default 500)
File sizeHISTFILESIZE (default 500)
File path~/.bash_history
Append modeshopt -s histappend
FilteringHISTCONTROL, HISTIGNORE
TimestampsHISTTIMEFORMAT
Clear memoryhistory -c
Write filehistory -w
Append filehistory -a
Re-execute last!!
SearchCtrl+R

Key takeaways:

  • The history list is in memory; the file is on disk. history -c clears only the memory. history -w writes the memory to the file. The shell writes the memory to the file automatically on exit, but only if it exits normally .
  • histappend controls whether the file is appended or overwritten. Without it, two terminals overwrite each other’s history. With it, the file accumulates all commands .
  • HISTCONTROL and HISTIGNORE filter what is saved. ignorespace skips commands starting with a space, ignoredups skips consecutive duplicates, and HISTIGNORE is a colon-separated pattern list .
  • !! re-executes the last command; !string re-executes the last command starting with a string; Ctrl+R searches incrementally. These are the three recall mechanisms that matter in daily use .
  • PROMPT_COMMAND="history -a" saves each command immediately. Without it, a crashed terminal loses the session’s history because the file is only written on exit .
  • HISTTIMEFORMAT enables timestamps. Without it, the history shows what ran but not when. With it, the timestamps persist across sessions in the history file .

Remember: Shell history is a two-layer system: the in-memory list that you interact with using history and !!, and the file that persists across sessions. The configuration variables control the size of both layers, what gets saved, and whether timestamps are recorded. The most common mistake is assuming that history -c erases the fileโ€”it does not, unless followed by history -w or a normal exit. The second most common mistake is not setting histappend, which causes two terminals to overwrite each other’s history. For the LFCS exam, know the configuration variables, the history flags, and the recall shortcuts, and know the difference between the memory and the file.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!