How to Use Command History Expansion in Shell (with Examples)
The command history expansion feature in shells like sh
, Bash, Zsh, rbash
, and ksh
allows users to efficiently reuse and manipulate previously executed commands. This feature can significantly enhance productivity by saving time and reducing the chance of error when retyping complex command sequences. Users can execute previous commands, modify arguments, and substitute parts of old commands with ease. History expansion is a powerful tool designed to streamline the command-line experience.
Use case 1: Run the Previous Command as Root
Code:
sudo !!
Motivation:
There are times when a user executes a command that requires administrative privileges to succeed. Instead of retyping the entire command with sudo
, the history expansion feature allows for quick elevation of privileges without redundant effort.
Explanation:
sudo
: This command allows a permitted user to run a command as the superuser or another user.!!
: This is a special history expansion syntax that is replaced by the last executed command in the shell history.
Example Output:
Imagine you previously executed:
apt-get update
Using sudo !!
would result in:
sudo apt-get update
Use case 2: Run a Command with the Last Argument of the Previous Command
Code:
command !$
Motivation:
Often, the last argument of a previous command might need to be reused in a different context. For instance, switching directories to manipulate a file. This expansion method efficiently grabs the last used argument.
Explanation:
command
: Placeholder for any new command you wish to execute.!$
: Expands to the last argument of the previous command.
Example Output:
For a previous command like:
mv file1.txt /path/to/destination/
Using:
echo !$
Results in:
echo /path/to/destination/
Use case 3: Run a Command with the First Argument of the Previous Command
Code:
command !^
Motivation:
Similar to the last argument, there are scenarios when the first argument of a prior command is needed for subsequent operations, such as manipulating a file by piped commands.
Explanation:
command
: A placeholder for any desired command.!^
: Expands to the first argument of the last command.
Example Output:
For the command:
cp file2.txt /backup/directory/
Executing:
ls !^
Would expand to:
ls file2.txt
Use case 4: Run the Nth Command of the History
Code:
!n
Motivation:
When needing to quickly rerun a specific earlier command without scrolling through the history manually, this expansion can directly execute the identified command.
Explanation:
!n
: Executes the nth command from the command history list, wheren
is the specific integer instance of said command.
Example Output:
Suppose history
displays:
5 git status
6 git pull
7 make build
Using:
!6
Outputs:
git pull
Use case 5: Run the Command n
Lines Back in the History
Code:
!-n
Motivation:
This form of history expansion is beneficial for accessing a command executed a specific number of steps previous to the current statement, streamlining repetitive task automation.
Explanation:
!-n
: Expands to the command executedn
lines before the current command position in the history.
Example Output:
Suppose you want to rerun a command two lines back:
!-2
If the history appears as:
9 echo "Hello"
10 ls
11 pwd
And you execute:
!-2
The result will be:
ls
Use case 6: Run the Most Recent Command Containing string
Code:
!?string?
Motivation:
This allows users to search and rerun the last command embedding a certain string, invaluable for recalling complex commands quickly without sifting through entire history logs.
Explanation:
!?string?
: Searches the command history for the most recent command that includesstring
.
Example Output:
With commands in history such as:
12 cd /project
13 compile app.c
14 grep "error" compile.log
Typing:
!?grep
Results in:
grep "error" compile.log
Use case 7: Run the Previous Command, Replacing string1
with string2
Code:
^string1^string2^
Motivation:
To quickly correct or alter a recently executed command, replacing a string with a new variant for immediate re-execution ensures a more efficient workflow without manual re-input.
Explanation:
^string1^string2^
: Substitutesstring1
withstring2
in the most recent command.
Example Output:
Given a prior command like:
vim somefile.txt
Using:
^somefile^otherfile^
The output would be:
vim otherfile.txt
Use case 8: Perform a History Expansion, but Print the Command that Would Be Run Instead of Actually Running It
Code:
!-n:p
Motivation:
This feature allows users to preview the expanded command to ensure accuracy, especially useful when dealing with complex history manipulations or when learning history expansion syntax.
Explanation:
!-n:p
: Displays the commandn
lines back in the history without running it, indicated by the appended:p
.
Example Output:
Consider if:
13 ls -l
14 cd /project
15 make build
Executing:
!-3:p
Displays:
ls -l
Conclusion:
Shell history expansion is a sophisticated feature that optimizes workflows by reusing and modifying previous commands with minimal input. Each use case outlines a unique scenario where such functionality comes in handy, enabling users to work more efficiently and accurately within the command-line interface. By mastering these techniques, users can greatly enhance their command-line productivity.