細かすぎて伝わらないシェルのhistory テクニック

# シェルでhistory は使いますよね？

シェルではhistory が大活躍します。同じようなコマンドはよくつかうので、それを呼び出すわけです。bash, zsh それぞれ微妙に使い方が異なりますが、やれることはだいたい同じです。

途中まではだいたい皆さんご存知かと思いますので復習です。細かすぎて伝わらないテクニックは最後に！

## その1

`矢印の上で戻る`

```
% echo "test1"
% echo "test2"
% echo "hello world"
```

例えばこんなコマンドを実行した後、矢印で上を一回押せば

```
% echo "hello"
```

が表示され、更にもう一度押せば

```
% echo "test2"
```

が表示されるので、最近実行したコマンドをもう一度見たい(実行したい)なんていうときには、上で戻るのがベストです。Emacs キーバインドであれば当然 `Ctrl + p` でOK

## その2

`Ctrl+r` を押すと **back incremental search** ができます。
zsh では `bck-i-search` と略され、bash では `reverse-i-search` と略されるやつです。これは文字通り、コマンドヒストリーに対して逆順(back / reverse)にインクリメンタルにコマンドを検索してくれます。

インクリメンタルとは、文字を入力するたびに検索を実行してくれるということで、例えば、先程の例であれば、

`Ctrl+r` を押しと

```
bck-i-search: _
```

と聞かれるので、そこで `e` とタイプすると

```
% echo "test1"
```

が表示されます。続けて、 `l` をタイプ(el とタイプした状態に)すると、今度は

```
% echo "Hello world"
```

が表示されます。これがインクリメンタル検索です。この検索は文字の先頭からという縛りも特に無いということもわかります。タイプした文字列にマッチするもののうちもっとも最近実行したコマンドが表示されます。

## 応用1

上記の2つは組み合わせられます。 `Ctrl+r` でインクリメンタルサーチを実行した後に、そこを起点に、さらに矢印の上下でコマンドヒストリーを行ったり来たりできます。例えば被検索効率の悪いコマンドを探したいときなどに、そのコマンドの直前でやったコマンドを思い出せれば、そこに対して `Ctrl+r` でたどって、そこを起点に矢印で移動するといった使い方です。

もちろんEmacs キーバインドであれば、矢印上下の変わりに、 `Ctrl+p` と `Ctrl+n` が使えます。

## 応用2

history / history-all コマンド

これらのコマンドを実行すると、コマンド履歴がバーっと画面に表示されます。

### bash

```bash
% history
```

```
   74  vi ./test.sh 
   75  . test.sh
   76  .
   77  date -d '1 month ago' +%Y-%m 
   78  echo -n -e \\0xEF\\0xBB\\0xBF > BOM
   79  cat BOM
   80  psql
   81  source activate py27
   82  source
   83  source activate py27
   84  history
```

### zsh

```zsh
% history-all
```

```
    1  1.4.2015 16:06  sl -la
    2  1.4.2015 16:07  zsh
    3  1.4.2015 16:08  brew 
    4  1.4.2015 16:08  which brew
    5  1.4.2015 16:09  brew install caskroom/cask/brew-cask
    6  1.4.2015 16:15  brew install git
    7  1.4.2015 16:16  brew search hg
    8  1.4.2015 16:20  brew install hg hg-flow
    9  1.4.2015 16:21  which hg
   10  1.4.2015 16:21  mkdir Work
```

見つけたコマンドはコピペで実行するのでも別にいいのですが、コマンド履歴番号を利用して実行することもできます。例えば、コマンド履歴番号の8番にある `brew install hg hg-flow` をもう一度実行したければ

```
$ 8!
```

これで実行できます。

また、 history はただのコマンドなので、パイプ `|` などで、 `head` や `tail`、それから `grep` と組み合わせることで検索も可能になります。検索でみつけたコマンドを実行したければ、その番号と `!` を使って実行です！

## 細かすぎて伝わらないテクニック

長めのコマンドを入力途中(入力後)に、いまこれ実行したら「アカン！」ってことに気づいた。
だがしかし、ここまで入力したものを捨てたくない...

```
% source ~/.pyenv/versions/anaconda3-2.3.0/envs/tensorflow/bin/activate
```

例えばこんなのをタイプして、「あ、これの前にxxx も実行しないといけないんだった...」となったとき。なくなく、ここまでタイプしたものを捨てたりしていませんか？

もう少しマシな例としても、これをコピペしてどこかに保存したりしていませんか？

そんなときに、history + **コメントアウト** を思い出してください。

```
% #source ~/.pyenv/versions/anaconda3-2.3.0/envs/tensorflow/bin/activate
```

bash であれば先頭に `#` を入れることで、このコマンド自体をコメントアウトできるので、これを実行すると、何も起こらないまま、めでたくコマンドヒストリーに登録されます。カーソルを行頭に持ってくるのは、Emacs キーバインドであれば `Ctrl+a` ですね。Mac ならそのまま使えるのかな(いろいろキーバインド変えているのでわからない...)

そして、先にやりたかったことをやってから、ゆっくりとヒストリーをたどって、今度は `#` を削除して実行すればOKです。

zsh では...

```
% #source ~/.pyenv/versions/anaconda3-2.3.0/envs/tensorflow/bin/activate
zsh: command not found: #source
```

zsh やcsh では`#` でコマンドのコメントアウトになりませんが、`#` を入れることで「そんなコマンドありませんよって」怒られて、実質なにも起こらないのでテクニックとしては同じように使えます。

もし思い出したら使ってみてください。

ちなみに、ハッとなったタイミングで別タブやscreen で他のコンソール立ち上げて、先にすべきことをやってから戻ってきて、この長いコマンドを実行するというのもいいのかもしれませんが、新規でコンソール立ち上げる一手間も惜しいですし、このディレクトリで実行したいという場合も多いと思いますので、このやり方が結構おすすめです。