This is written from the perspective of a macOS user; specifically, a macOS Catalina (or later) user. Under macOS Catalina, Apple changed the default shell from bash
to zsh
. However, most of the material here is completely relevant for bash
users as well. Some of the semantics will change, but the operation of the shell history is the same for bash
and zsh
.
If you open a terminal - for example Terminal.app
in macOS - and you enter a command at the prompt, that command is saved into the command history. In fact, depending upon how command history is configured on your machine, every command you have ever issued could be saved into a command history. Control and maintenance of the command history is a function of the shell being used. Different shells manage the command history in different ways, though they also have much in common. If you switch between shells, your command history will be contained in different memory locations and different files.
The command history is useful because we often use the same - or similar - commands repeatedly. These commands may contain long lists of arguments and options that are highly specific, and often arcane. Considerable time and effort may be invested in getting a particular command "tweaked" to perform a certain function in a very specific way. The utility of a command history will be obvious to anyone after using rsync
or ffmpeg
or git
for a while.
The reader is now hopefully motivated, and asking, "How do I access my command history?" As with many things, there are many means to access the command history. Let's start with one of the simplest - history
. The obligatory man page:
% man history
unfortunately does not reveal much that is helpful. The history
command is built in to the shell - as are many other commands:
As it turns out, the history
command is useful for listing the command history, but not particularly helpful at finding the command of interest. Nevertheless, as we shall see, it does come in handy, and it's simple to use. The examples below illustrate some uses for the history
command. Feel free to try them & return here afterward.
Simpler still is using the up (⬆︎) and down (⬇︎) arrows on the keyboard to scroll up and down in the command history. This is easily demonstrated in any active terminal window - each press of an up or down arrow button will advance or return one command further into the command history stack. Like the history
command, this is useful, but not particularly efficient for older commands (further up in the stack) - or for those using the CLI frequently.
Before discussing other methods for accessing the command history, let's briefly focus on how the shell maintains the command history, and by what means the user may exercise control and express his preferences.
As mentioned above, the command history is a function of the shell, and for purposes of this recipe the shell of interest is zsh
- currently the default shell in macOS. The file /etc/zshrc
contains your machine’s default settings, including a few relevant to the command history. Following are the defaults as of this writing:
% less /etc/zshrc # peruse the default settings for zsh
...
# Save command history
HISTFILE=${ZDOTDIR:-$HOME}/.zsh_history
HISTSIZE=2000
SAVEHIST=1000
...
Let's briefly review these variables:
HISTSIZE
declares the size of the session history; session as in an instance of the shellSAVEHIST
defines the size of the history fileHISTFILE
simply declares the name of the user's history file, and where it's stored.
Note that the command history is made up of two separate entities: the session history and the history file. They are "linked" and inter-operate in the following fashion:
- when a
zsh
session is closed, the session history is concatenated to the history file - when the session history reaches its limit, the overflow is concatenated to the history file
- when you go beyond the oldest command in the session history, you transition to the history file
- the command history of a new session, before any commands are issued, is entirely from the history file
- commands in the session history are unique to that session; the history file contains command history from (potentially) all sessions, past and present.
The following graphic attempts to illustrate some of the relationships between the session histories (one per session), and the history file:
If you've been using zsh
for a while, you can open your command history file at ~/.zsh_history
and see what it contains. Likewise, with this file open and in view, the operation and interaction of the session history and the history file may be directly observed. (You may want to temporarily reduce HISTSIZE
and SAVEHIST
to save time before doing so. Backing up your .zsh_history` may also be warranted.)
Given the above, it is left as an exercise for the reader to determine the logic behind Apple's default settings for HISTSIZE
and SAVEHIST
in /etc/zshrc
. That is to say, the deep thinking that went into setting SAVEHIST
to one-half the size of HISTSIZE
. Extra points to the reader who shares this revelation!
Some may be tempted to make changes to the default values of SAVEHIST
and HISTSIZE
. If you wish to make changes, please note:
NOTE: When changing values of
HISTSIZE
orSAVEHIST
, heed the instructions in/etc/zshrc
:# Setup user specific overrides for this in ~/.zshrc
At one time, Apple included this warning in
/etc/zshrc
: Do not make changes in/etc/zshrc
I have yet to see (as of Ventura) Apple include any practical history settings in ~/.zshrc
; consequently, you must do this yourself. You should refer to man zshoptions
(specifically the "History" section) when making these changes. Also note that in man zshoptions
, it is not always crystal clear whether they are referring to session history - or the history file.
With relationships between the command history components made clear, let us explore some additional methods for accessing the command history:
- up (⬆︎) and down (⬇︎) arrows on the keyboard scroll sequentially through the command history
2. the
history
command and its options will list selected commands 3. controlr at the command prompt will search & match items in your command history
4.!!
runs the previous command; e.g.sudo !!
executes the previous command withroot
privileges
These tools, coupled with an understanding of the command history components and how they interact is enough to begin using the command history productively. A few examples follow with more details.
Enter controlr at the command line to see the bck-i-search:
prompt for a search term:
%
bck-i-search: _
Assume you need to find the command for an ssh
connection; enter ssh
as the search term:
% ssh seamus@macbuntupro.local # <-- a finding from command history
bck-i-search: ssh_
This is the most recent entry in the command history. If this is NOT the host/command you're searching for, simply enter controlr again to go to the next previous command. Continue controlr until the command/host of interest is found. When found, use the right arrow (➡︎) to select that command and end the search. This will place the selected command on the command line where it may be edited or executed (return). Use controlg to terminate the search & return to a blank command line.
Simply running the command history
from the CLI lists the 16 most recent commands in the command history. No idea why 16
is the "magic number" here... If you know the location of a particular command in the command history, that may be specified as an argument. This is rarely useful, except perhaps to list all commands; i.e. history 1
- or more likely history 1 | less
. Perhaps slightly more useful is piping the entire history 1
output to grep
:
% history 1 | grep ssh
# --OR--
% history 1 | grep ssh | less
These are only two examples. The REFERENCES below may provide more advanced methods for searching the command history more efficiently.
- Better command history browsing in Terminal - get
history-search-forward
setup using~/.profile
- Better zsh History
- A Guide to ZSH History
- A SO Q&A to get
history-search-forward
usingbind
in~/.zshrc
- Q&A: How can I search history with text already entered at the prompt in zsh?
- Docs: zsh Line Editor's History Control ; see also ZLE Builtins
- Lorna Jane's blog on 'Navigating Bash History with Ctrl+R'
- How To Set Up History-Based Autocompletion in Zsh