In my article, Parsing Bash history, I demonstrated how to reference items in your shell history
by line number as well as by word position. Once you've mastered parsing Bash history
by line and word index, you can benefit from the modifiers available to the history
command.
The histexpand shell option
Before discussing history
parsing, it's worth mentioning that the exclamation point (!
) notation is only available to your Bash shell thanks to the histexpand
option. Because histexpand
is enabled by default, many users never give it much consideration. However, it's the option that enforces expansion of a !
to the list of history
entries.
Should the option be toggled off, you lose this functionality. For example:
$ echo foo
$ set +o histexpand
$ !-2
bash: !-2: command not found
$ set -o histexpand
$ !-3
echo foo
foo
Generally, histexpand
is on by default, except in non-interactive shells (for instance, in a shell script). Should history
shorthand ever fail you, you can either activate histexpand
as a shell option or else use the full history
command implied by histexpand
:
$ echo foo
$ set +o histexpand
$ history -p !-2
echo foo
foo
In a shell script, you must activate history
and provide a location where history
can be saved:
HISTFILE=/tmp/history.log
set -o histexpand
set -e
## some code here
## clean up
rm /tmp/history.log
An advantage of leaving histexpand
deactivated is that you lose the verbosity of the results of history
actions. For instance, with histexpand
activated, the first thing returned to your shell after a history
command is the expanded version of what's being run:
$ set -o histexpand
$ echo foo
foo
$ !!
echo foo
foo
With histexpand
toggled off, your history
command is longer, but the results are more terse:
$ set +o histexpand
$ echo foo
foo
$ !!
foo
Whether you find a use for history
in a shell script is up to you, but history
modifiers have some interesting shortcuts that make them particularly convenient in some cases.
History modifiers
Modifiers to history
selections are designated by a colon (:
) followed by one modifier character. Some modifiers may be combined with others.
Filename suffix
To drop the suffix of an argument, use the r
modifier.
This is similar to basename
.
$ ls -lgGh aLongFileNameWith-a_complex-syntax-1.tgz
-rw-r--r-- 1 0 Mar 9 11:23 aFileNameWith-a_complex-syntax-1.rev.tgz
$ echo !!:2:r
echo aLongFileNameWith-a_complex-syntax-1
aLongFileNameWith-a_complex-syntax-1
The r
modifier isn't super-intelligent. It just finds the final dot in a filename and chops off the suffix, which sometimes may not match what you think of as the file suffix, so in some ways, basename
offers greater flexibility.
$ set +o histexpand
$ ls -lgGh aLongFileNameWith-a_complex-syntax-1.tar.gz
$ echo !!:2:r
aLongFileNameWith-a_complex-syntax-1.tar
The opposite result can be attained with the e
modifier:
$ set +o histexpand
$ echo aLongFileNameWith-a_complex-syntax-1.tgz
aLongFileNameWith-a_complex-syntax-1.tgz
$ echo !!:2:e
.tgz
Filenames
A simple version of dirname
is available with the h
modifier:
$ set +o histexpand
$ echo src/spacer.sh
src/spacer.sh
$ echo !!^:h
src
And the other side of that expression is available with the t
modifier:
$ set +o histexpand
$ echo src/spacer.sh
src/spacer.sh
$ echo !!^:t
spacer.sh
String substitution
Possibly the most broadly useful modifier of history
is string substitution. For instance, any admin of a mixed environment has typed this into a Red Hat Enterprise Linux box at some point:
$ sudo apt install tmux
Such a mistake is easy to fix with string substitution:
$ ^apt^dnf
sudo dnf install tmux
You can even add on some options:
$ ^apt^dnf -y
sudo dnf -y install tmux
This history
syntax is shorthand for the s
modifier. The full syntax is, for example, !!:s/apt/dnf
and therefore can be useful for items several lines back in your history
. Assume you issued a useful command three commands back, and want to run a similar command now:
$ !-3:s/vi/emacs/
sudo dnf install -y emacs
Like sed
, this substitution by default only occurs once, but you can make it global (in relation to the line you're recalling) with the g
modifier:
$ pip update pip
[...]
$ !!:gs:/pip/pip3/
pip3 update pip3
Safety first: how to perform a history dry-run
Pressing Return
after a modified history
line can sometimes be stressful, especially when the line you want to re-run is nestled between particularly dangerous commands or affects important files. If you want to verify the command you're about to modify and run, you can use the p
modifier at the tail end of a history
modification.
$ !-32:0-:s/mv/trash/:p
trash important.txt status.txt pay.txt
The command you see as a result is the expanded item from history
, but it hasn't been run yet. You can run it manually, by pressing the Up
arrow or Ctrl+P
, now that it's been resolved for you. Using verification (p
) is generally a good idea if you're new to using the history
command in production.
Wrapping up
Your Bash history can be useful for many things, whether it's looking back at what you've been doing all day, or just making your work more efficient by reusing chunks of information you've already worked to figure out. The more you practice with history modifiers, the more useful they become. Allow yourself to (carefully) stumble through some as you learn the syntax, and soon you'll be recalling commands and arguments with fewer key-presses than ever before.
[ Want to try out Red Hat Enterprise Linux? Download it now for free. ]
執筆者紹介
Seth Kenlon is a Linux geek, open source enthusiast, free culture advocate, and tabletop gamer. Between gigs in the film industry and the tech industry (not necessarily exclusive of one another), he likes to design games and hack on code (also not necessarily exclusive of one another).
チャンネル別に見る
自動化
テクノロジー、チームおよび環境に関する IT 自動化の最新情報
AI (人工知能)
お客様が AI ワークロードをどこでも自由に実行することを可能にするプラットフォームについてのアップデート
オープン・ハイブリッドクラウド
ハイブリッドクラウドで柔軟に未来を築く方法をご確認ください。
セキュリティ
環境やテクノロジー全体に及ぶリスクを軽減する方法に関する最新情報
エッジコンピューティング
エッジでの運用を単純化するプラットフォームのアップデート
インフラストラクチャ
世界有数のエンタープライズ向け Linux プラットフォームの最新情報
アプリケーション
アプリケーションの最も困難な課題に対する Red Hat ソリューションの詳細
オリジナル番組
エンタープライズ向けテクノロジーのメーカーやリーダーによるストーリー