Working in a server environment will require you to use the command line frequently. You’ll generally be Use Bash History Commands and Expansions on a Linux VPS
It’s likely that throughout a terminal session you will be typing versions of the same instructions and repeating some commands several times. Even though entering commands repeatedly can be helpful at first, eventually, it gets irritating and disruptive.
Thankfully, the bash shell’s history features are somewhat well-developed. If you know how to use and manage your bash history, you can spend less time typing and more time doing actual work. Many developers are familiar with the principle of Don’t Repeat Yourself, or DRY. By effectively utilizing bash’s history, you can work more in accordance with this concept and increase your productivity.
You need to have access to a computer running an operating system based on Linux in order to continue with this tutorial. This could be a virtual private server that you have created an SSH connection to, or it could be your local computer. This lesson should work on any machine running any version of Linux, even though the examples were tested on a Linux server running Ubuntu 20.04.
Before attempting to follow this lesson on a remote server, we recommend that you complete our Initial Server Setup tutorial. This will provide you with a secure server environment where you may practice your Linux skills. It will come with a non-root user with sudo rights and a firewall configured using UFW.
Setting History Defaults:
Before you begin using it, adjust a few bash settings to maximize the usefulness of your command history. These stages aid in the process of finding and executing previously executed commands, although they are not necessary.
Open your ~/.bashrc file in your preferred text editor to change these settings. Here, nano will be used:
- nano ~/.bashrc
Look for the options HISTSIZE and HISTFILESIZE. Feel free to change the values if they are set. Add these settings right now if they aren’t already in your file. Saving 10,000 lines to disk and loading the final 5,000 lines into memory will suffice for the purposes of this tutorial. For the majority of systems, this is a conservative estimate, however you can lower these figures if you observe a performance impact:
. . .
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
. . .
By default, bash writes its history at the end of each session, overwriting the existing file with an updated version. This means that if you are logged in with multiple bash sessions, only the last one to exit will have its history saved.
You can work around this by setting the
histappend setting, which will append instead of overwriting the history. This may be set already, but if it is not, you can enable this by adding this line:
. . .
shopt -s histappend
. . .
With that, you’ve adjusted how your shell handles your command history. You can now get some practice finding your previous commands with the
Reviewing your Previous Bash History:
The way to review your bash history is to use the
history command. This will print out our recent commands, one command per line. This should output, at most, the number of lines you selected for the
HISTSIZE variable. It will probably be fewer at this point:
. . .
43 man bash
44 man fc
45 man bash
46 fc -l -10
48 ls -a
49 vim .bash_history
51 man history
52 history 10
history returns is associated with a number for easy reference. This guide will go over how this can be useful later on.
You can truncate the output by specifying a number after the command. For instance, if you want to only return the last 5 commands that were executed, you can type:
- history 5
51 man history
52 history 10
54 history 5
To find all of the
history commands that contain a specific string, you can pipe the results into a
grep command that searches each line for a given string. For example, you can search for the lines that have
cd by typing:
- history | grep cd
33 cd Pictures/
37 cd ..
39 cd Desktop/
61 cd /usr/bin/
83 cd /etc/
86 cd resolvconf/
90 cd resolv.conf.d/
There are many situations where being able to retrieve a list of commands you’ve previously ran can be helpful. If you want to run one of those commands again, your instinct may be to copy one of the commands from your output and paste it into your prompt. This works, but bash comes with a number of shortcuts that allow you to retrieve and then automatically execute commands from your history.
Executing Commands from your Bash History:
Although it can be helpful, printing your command history just serves as a reference for those commands.
Any command that a history operation has returned can be quickly recalled and executed by using its number, which is accompanied by an exclamation sign (!). If the results of your history match those in the preceding section, you might easily view the man page for the history command by typing:
This will trigger the command linked to history number 51 to be recalled and executed instantly.
You can also use the!-n syntax, where “n” is the number of previous commands you wish to remember, to execute commands relative to your present position.
Let’s take an example where you executed the next two commands:
- ls /usr/share/common-licenses
- echo hello
If you wanted to recall and execute the command you ran before your most recent one (the
ls command), you could type
You could run to carry out the previous command you executed again!–1. Nevertheless, bash offers a shortcut that consists of two exclamation points that will execute the most recent command in place of the previous one:
This is frequently used by folks who input commands but forget they require sudo privileges in order for them to run. typing quickly!will run the command again with sudo before it:
- touch /etc/hello
touch: cannot touch `/etc/hello': Permission denied
- sudo !!
sudo touch /etc/hello
[sudo] password for sammy:
This demonstrates another property of this syntax: these shortcuts are pure substitutions, and can be incorporated within other commands at will.
Searching through Bash History:
While running the history command through grep can help focus the results, it isn’t always the best option.
Bash has historical search functionality. Using the CTRL + R key combination to search backward in time (with the most recent results returned first) is the standard method for doing this.
For example, you can start entering a portion of the previous command by hitting CTRL + R. The command simply needs to be partially typed out. In case it corresponds with an undesirable command, you can hit CTRL + R once again to view the subsequent outcome.
In the event that you inadvertently execute the desired instruction, you can reverse your path by pressing CTRL + S. If you want to search forward after utilizing the keys in the previous section to get to a different point in your history, this can also be helpful.
Note that the CTRL + S key combination is often mapped to exit the current terminal session. This will “freeze” your terminal and stop any attempts to use CTRL + S to bash. Press CTRL + Q to resume the session after it has frozen.
This suspend and resume feature is not needed in most modern terminals, and you can turn it off without any problem by running the following command:
- stty -ixon
stty is a utility that allows you to change your terminal’s settings from the command line. You could add this
stty -ixon command to the end of your
~/.bashrc file to make this change permanent as well.
If you try searching with
CTRL + S again now, it should work as expected to allow you to search forwards.
Searching after You’ve Typed Part of the Command:
Entering a portion of a command and then realizing that you have already run it and can look it up in the history is a common occurrence.
Using what is already on your command line, the proper way to search is to use CTRL + A to move your cursor to the beginning of the line, CTRL + R to call the reverse history, CTRL + Y to paste the current line into the search, and CTRL + R once more to search in reverse.
Let’s say, for example, that you wish to update your Ubuntu system’s package cache. Although you recently typed this out, you didn’t consider that until after you typed the sudo in the prompt once more:
At this point, you realize that this is an operation you’ve definitely done in the past day or so. You can press
CTRL + A to move your cursor to the beginning of the line. Then, press
CTRL + R to call your reverse incremental history search. This has a side effect of copying all of the content on the command line that was after our cursor position and putting it into your clipboard.
CTRL + Y to paste the command segments that you just copied from the command line into the search. Lastly, press
CTRL + R to move backwards in your history, searching for commands containing the content you’ve just pasted.
Using shortcuts like this may seem tedious at first, but it can be quite useful when you get used to it. It is extremely helpful when you find yourself in a position where you’ve typed out half of a complex command and know you’re going to need the history to finish the rest.
Rather than thinking of these as separate key combinations, it may help you to think of them as a single compound operation. You can just hold the
CTRL key down and then press
Y, and then the
R key down in succession.
Getting Familiar with More Advanced History Expansion:
This guide has already touched on some of the most fundamental history expansion techniques that bash provides. Some of the ones we’ve covered so far are:
!!: Expand to the last command
!n: Expand the command with history number “n”.
!-n: Expand to the command that was “n” number of commands before the current command in history.
The above three examples are instances of event designators. These generally are ways of recalling previous history commands using certain criteria. They are the selection portion of your available operations.
For example, you can execute the last
ssh command that you ran by typing something like:
This searches for lines in your command history that begin with
ssh. If you want to search for a string that isn’t at the beginning of the command, you can surround it with
? characters. For instance, to repeat a previous
apt-cache search command, you could likely run the following command to find and execute it:
Another event designator you can try involves substituting a string within your last command for another. To do this, enter a caret symbol (
^) followed by the string you want to replace, then immediately follow that with another caret, the replacement string, and a final caret at the end. Don’t include any spaces unless they’re part of the string you want to replace or part of the string you want to use as the replacement:
This will recall the previous command (just like !!), search for an instance of original within the command string, and replace it with replacement. It will then execute the command using the replacement string. This is useful for dealing with things like misspellings. For instance, say you mistakenly run this command when trying to read the contents of the /etc/hosts file:
- cat /etc/hosst
cat: /etc/hosst: No such file or directory
Rather then rewriting the entire command, you could run the following instead:
This will fix the error in the previous command and execute it successfully.
By reading this guide, you should now have a good idea of how you can leverage the history operations available to you. Some of these will probably be more useful than others, but it is good to know that bash has these capabilities in case you find yourself in a position where it would be helpful to dig them up.
If nothing else, the
history command alone, the reverse search, and the basic history expansions can do a lot to help you speed up your workflow.
Get more information about
Extracting a Substring in Bash