Motivation
gitとかdockerとかkubectlとか、引数やオプションがてんこ盛りのコマンドを使っていると、過去に実行したコマンドを検索して参照したくなる。
最も簡単な方法:reverse-i-search
ターミナルでC-r
をタイプすると、過去のコマンドをインクリメンタル検索できる。検索は部分一致。C-r
をタイプするたびに別な候補が表示される。このようにして順に表示した候補は、C-s
で逆順に表示できる。ただし、C-s
はスクリーンロックという機能にバインドされていることが多い(ターミナルが反応しなくなったように見えて焦る。C-q
で解除できる)。以下のコマンドを実行してこの機能のバインドを解除しておく。
$ stty stop undef # 毎回実行するのが面倒なので、.bashrcに書いておくとよい
検索したコマンドは、リターンキーでそのまま実行することもできるし、カーソルを移動して一部を編集することもできる。
複数の単語で絞り込む:history + grep
historyコマンドを実行することで、過去に実行したコマンドを一覧できる。これらのコマンドには番号が振られており、例えば番号42のコマンドなら、
$ !42
のように実行できる。実行するのではなく、入力された状態(リターンキーを押せば実行できる状態)にしたければ、コマンド末尾でESC C-e
をタイプする。
historyコマンドの結果は、もちろんgrepできる。
# 例:gccのバージョン切り替えってどうやってたっけ?
$ history | grep gcc | grep alternative
エイリアスにしておくと使いやすいのでは。
$ alias hg='history | grep $1' # .bashrcに書いておく
$ hg gcc | grep alternative # タイプ量が少なくなった
凝ってみる:peco
正直なところ、上記の2手段で十分だと思うが、オーバーエンジニアリングする。Emacsのhelmみたいに、{検索ワード1} {検索ワード2} ...
と入力するたびインタラクティブに絞り込みしたい。
調べてみると、pecoというインタラクティブなフィルタツール(コマンド?)を使うのが良さそう。bash/zshのヒストリをpecoで便利にするを参考に導入してみる。
まずはpecoをインストールする。幸いbrewにformulaeがある。
$ brew install peco
ターミナルから使うための設定を.bashrcに書く。
peco_search_history() {
local l=$(HISTTIMEFORMAT= history | \
sed -e 's/^[0-9\| ]\+//' -e 's/ \+$//' | \
sort | uniq | \
peco --query "$READLINE_LINE")
READLINE_LINE="$l"
READLINE_POINT=${#l}
}
bind -x '"\C-r": peco_search_history'
historyコマンドの結果に対し、sedで行頭の空白とコマンド番号を取り除く1。また、行末の余分な空白も取り除いておく。その後、sortとuniqで重複したコマンドを取り除く(sedで行末の空白を取り除いておかないと、見た目が同じコマンドが空白の有無のせいで重複して残ってしまうことに注意)。この結果をpecoに受け渡す。
また、検索をC-g
で中止するため、~/.peco/config.jsonを作成し、設定を書く:
{
"Keymap": {
"C-g": "peco.Cancel"
}
}
これで、C-r
でhelmライクな過去コマンド検索ができるようになった。
-
historyコマンドではなく、単に
cat .bash_history
でもいいのかも。こうすればsedで行頭の不要部分を取り除く手間がいらない。 ↩