Repeating commands on Linux with or without changes

There are a lot of ways on Linux to make repeating commands easier than retyping them, and here's a nice collection of them.

repetition magritte derby hat dock horizon multiply
Getty Images

Life on the command line on Linux is clearly something most of us enjoy, but typing the same command again and again can become tiresome. To avoid that boredom, this post explains a number of ways that you can make repeating commands – or repeating commands but with some changes – a lot easier than you might expect.

Rerunning the previous command

First, the easiest way to repeat a command is simply by typing !!. If you were logged into a Linux server and waiting for a coworker to log in, for example, you might want to repeat the who command shown below until you see your coworker’s username. Typing !! after the initial who command will do this for you.

$ who | awk '{print $1,$2}'
shs pts/1
$ !!
shs pts/1
$ !!
shs pts/1
nemo pts/2	<== Yay, he just showed up!

Exploring your command history

History files are generally fairly long – often holding 1,000 commands or more. You can view how many commands will be remembered for your account by using this command:

$ echo $HISTSIZE
1000

However, you don't have to look at hundreds or thousands of prior commands when you want to view your command history. You can look at only the most recent commands by specifying how many prior commands you want to have displayed. This command will only show the most recent 5 commands:

$ history 5
 1011   28/07/22 14:14:04 who | awk '{print $1,$2}'
 1012   28/07/22 14:15:18 vi timetable
 1013   28/07/22 14:15:43 who | awk '{print $1,$2}'
 1014   28/07/22 14:21:57 echo $HISTSIZE
 1015   28/07/22 14:24:39 history 5

Reusing commands from your command history

Another easy way to repeat commands is to reference your command history by typing something like the commands below that would rerun the command in your history command output after you find it using grep, and then type ! followed by the sequence number associated with the command.

$ history | grep Sydney
865  27/07/22 12:02:50 date -d 'TZ="Australia/Sydney" 04:30 next Monday'
$ !865
date -d 'TZ="Australia/Sydney" 04:30 next Monday'
Sun Jul 31 02:30:00 PM EDT 2022

Rerunning commands with changes

You can also rerun commands but change them in the process. For example, if you typed “echo hello there”, you could use !! followed by a : and the string that replaces “there” with “world” to run it again:

$ echo hello, there
hello, there
$ !!:s/there/world/
echo hello, world

In the case of echoing "hello", it would be easier to just type “echo hello, world”, but for many commands, this would not be the case. If you wanted to look at a calendar for the month of August over a period of some number of years, for example, you could run commands like these (output not shown):

$ cal aug 2020
$ !!:s/020/021/
$ !!:s/1/2/ 

Remember that !! recalls the command that was run, not what you typed to create it. So, the second command replaces "2020" with "2021" and the third replaces "2021" with "2022".

You can also reuse commands from your command history in this way. Here's an example that reruns a command in your command history replacing "today" with "tomorrow":

$ !1012:s/today/tomorrow/

Avoiding saving commands to your command history

You can also decide not to save the commands that you have used in your current login session in your history file by running a command like this one:

$ unset HISTFILE && exit

That command will exit the session without saving any of the commands.

You can also use the HISTIGNORE setting to avoid saving commands that will be much easier to type again than find in your command history. For example, you might not want to bother storing commands like cd, ls, pwd, clear, man or history in your .history file since you wouldn't likely to refer to your command history to reuse them.

$ grep HISTIGNORE .bashrc
HISTIGNORE="cd:pwd:clear:ls:man:history"

Reusing a command argument

Another interesting trick is to reuse a command argument as in following commands. The $_ in the second command represents the last argument in the first command. The commands below create a new directory and then move into it without having to type the directory path a second time.

$ mkdir /home/$USER/tools/mytools/settings
$ cd $_

The example command below confirms that $_ only captures the final piece of text:

$ echo Have a nice day!
$ echo $_
day!

Reusing a portion of a command

If you want to create a series of directories with names beginning with the current date but followed by a set of additional endings, you could use a command like this to make it a little less trouble:

$ mkdir -v `date '+%Y%m%d'`_{reports,images,notes}	
mkdir: created directory '20220728_reports'
mkdir: created directory '20220728_images'
mkdir: created directory '20220728_notes'

The -v option used with the mkdir command provides the confirmation that each directory was created.

If you need to create a directory structure like what is shown above routinely, it would probably be a good idea to turn a command like that into an alias so that it’s easy to reuse.

Saving your commands as aliases

Of course, one of the easiest ways to repeat commands that you use often, especially complex ones, is to simply turn them into aliases and save those aliases in your .bashrc file so they're available every time you log in.

The alias below creates a list of all of the months of the year in their proper order.

$ alias show_months='printf "%02d/01/2000\n" {1..12} | LC_ALL=C date +%B -f-'
$ show_months
January
February
March
April
May
June
July
August
September
October
November
December

Remember to give your aliases meaningful names so that you can use them without having to search for them in your .bashrc file every time.

Wrap-up

There are a lot of ways to make Linux commands, especially complex commands, easier to repeat. Let’s keep making working on the command line fun.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Related:

Copyright © 2022 IDG Communications, Inc.