Bash History

Mohamed Vishah
digitalraajje
Published in
7 min readFeb 13, 2020

Command-line history

Bash is a command like shell, a program that provides an environment to run command line programs. Typical programs we use every day use a graphical user interface, where users provide input to the programs through clicking buttons, or selecting options from dropdown menus or entering text into text boxes.

Unlike these GUI applications, running command-line programs require writing the name of the program on a command line shell. Instead of running different functions by clicking options on the menu bar, in command-line programs, options to instruct different actions on the program are written as text along with the command. In addition to these, the user has to provide any other data required for the program to run.

For example:

* Command

ls -l /var/log

*Output

-rw-r — — — 1 root adm 2043 Sep 23 06:25 syslog.2.gz

-rw-r — — — 1 root adm 25081 Sep 21 06:25 syslog.3.gz

-rw-r — — — 1 root adm 25830 Sep 16 06:25 syslog.4.gz

-rw-r — — — 1 root adm 15346 Sep 7 06:25 syslog.5.gz

-rw-r — — — 1 root adm 26010 Aug 30 06:25 syslog.6.gz

-rw-r — — — 1 root adm 64550 Aug 25 06:25 syslog.7.gz

where ‘ls’ is a command that lists contents of a directory. ‘-l’ instructs ls program to show the output in a more detailed fashion. ‘/var/log’ is the directory whose contents we want to list.

Output of the commands can also get redirected as the input of other programs by using pipes. ‘wc’ is another command which accepts a file as input and ‘-l’ option to ‘wc’ will display the number of lines in the given file. Instead of providing a file for ‘wc’ , in the following example, we are passing the output of another command as the input of wc command. The resulting output will be 6 for the output of ls above.

ls -l /var/log|wc -l

Combination of commands using PIPE ‘|’ can frequently get longer than this. In addition typically users will enter a lot of commands in succession.What if a user wants to re-execute the above command but with a different directory ‘/etc/sysconfig/’?.

It is tedious to rewrite long commands over and over again.Performing tasks in such a redundant fashion is not a UNIX way of doing things. This is where bash history functions come to play.

The bash shell comes packed with many tricks to help in easing and speeding up the workflow of sysadmins and developers. All the commands entered in the terminal are stored in bash history file up to a certain limit. The number of commands maintained by the bash history file can also be adjusted by the users by modifying the HISTSIZE setting in the bash configuration file. Each of the commands are numbered in the file so that it can be referenced easily and the sequence in which they were entered by the user can easily be identified.

Typing the command `history` will show all the commands stored in the history file. If only the last 5 commands are to be viewed, pass a number — 5 in this case — as an argument to the command.

history 5

50 history

51 man history

52 history 10

53 history

54 history 5

Output of the `history` command(which shows all commands entered in history) when piped to the grep command (which searches for a string in a file), will show all entries in history which has the matches search string.

For example, to list all instances where cd command was issued, type the following.

history | grep cd

33 cd Pictures/

37 cd ..

39 cd Desktop/

61 cd /usr/bin/

In addition to piping history command output to grep command to perform search, bash also provides a more convenient key combination to perform search. By pressing CTRL-r key and beginning typing part of the command you want to recall, bash will show the most immediate match for the entered search query. If you would like to go further back in history for the searched matches, press CTRL-r as many times as needed.

If you already entered part of a command to the terminal, and wanted to search in history for the command, instead of pressing CTRL-r and retyping the search query, you can first press CTRL-a, which will place the cursor at the beginning of the line. Then press CTRL-r which will start the reverse history search process. Now you can press CTRL-y to paste what was already entered terminal as a search string and then press CTRL-r to search backward in history.

If you don’t want to search history for a string, but only want to scroll through history one by one, use CTRL-p which is used to scroll back in history, and CTRL-n to scroll forward.

Event Designators

Since each command we issue has an indexing number associated with it in bash history, this number in turn can be used to rerun the command. For example by typing exclamation mark 50 will recall and re execute the command associated with history index number 50

!50

In addition to referring to a previous command by its index number, you can also refer to a previous command by using its relative position in history. The syntax used for this is !-n where n is the relative position in history. If we want to re-execute the previous command the syntax will be !-1, If we want to re-execute the command we executed before that it will be !-2 and so on.

10 cat rat.txt

11 ps -e

12 ls *fish*

13 ls *cat*

14 ls *meow*

To view files and directories with the word ‘fish’ in its name we used `ls *fish*`. This command was the third last command we have issued. Hence to rerun this command we have to type the following.

!-3

Bash provides a simpler way to re-execute the previous command, instead of using !-1. To re-run previous command you can also use the following.

!!

!-n and !! contains the full strings of the commands pointed by them. This means that in addition to using these bash history shortcuts to recall previous commands as is, we can use these pointers to modify a previous command.

For example after running` ls *.xml ` to view all xml files in the current directory, it is also then required to list all php files in addition to xml files. For that we can run `!! *.php` which will recall the previous command with !! and append the search wildcard ‘*.php’ to it.

ls *.xml ← list all xml files in the current directory

phpunit.xml ← output of above command

!! *.php ← typing this

ls *.xml *.php ← results in this

phpunit.xml server.php ← output of above command

To search back in history for a command beginning with a string, and if a match is found to immediately execute it use ! followed by search string.

!ls

search backward in history for a line beginning with `ls` and if match is found immediately to execute it.

If the search string can be anywhere in the command, not necessarily at the beginning, you can use !?search-string? syntax.

!?cat?

if the most recent entry in history matching the string ‘cat’ is

`vim cat.txt`

bash will immediately run that command, which opens the file cat.txt in vim text editor.

If you would like to open the file in emacs text editor instead, you can perform a search and replace functionality of bash history. History search and replace has the following syntax:

^search^replace^

So to perform the task at hand, we will have to issue

^vim^emacs^

Word Designators

Word designators are used to match part of the command line, which are recalled by an event designator. The parts matched are represented by parts in the command line which are surrounded by white space. Words in a command line can be represented by numbers or special characters representing their position in the command-line string. Word designators are given after entering `:` character after an event designator.

For example !! event designator points to and contains the previous command issued. If the previous command is `ls /var/www/logs/`, to change the working directory to /var/www/logs without typing the path again, use `cd !!:1` where `:1` represents the first argument or first word in the string contained in the event designator.

In the example !! refers to `ls /var/www/logs` and the first word in it is `/var/www/logs`.

ls /var/www/logs

cd !!:1

where !! is `ls /var/www/logs` and

:1 resolves to `/var/www/logs` and

cd !!:1 resolves to `cd /var/www/logs`

ls command can have more than one argument. For example

ls a/ b/ c/ d/

shows the list of files and directories in a, b,c and d directories. Here the first argument to ls is a/ which can be represented by ^ and the last argument is d/ which can be represented by the $ symbol. To represent all arguments * can be used

Wild cards can also be used to match arguments in a word designator.

!!:1*

resolves to a/ b/ c/ d/

!!:1-$

resolves to a/ b/ c/ d/

!!:^-3

resolves to a/ b/ c/

!!:*

resolves to a/ b/ c/ d/

Unix philosophy is all about making it efficient for the users to perform tasks. Using bash history functions will let you reduce your typing, speed up your work and help to reduce mistakes.

--

--