↩️

zshのhistoryに実行に失敗したコマンドを残さない

2025/02/15に公開

履歴ファイルに保存されるコマンド履歴ですが、一般的には失敗したコマンドも保存されます。

私はコマンド履歴からの補完を多様しているので、typo や間違ったコマンドまで保存されてしまうと、それらのコマンドまで補完候補に含まれてしまいノイズになってしまうので、失敗したコマンドは履歴に保持しないようにします。

実行環境は zsh 5.9 です。

$ zsh --version
zsh 5.9 (arm-apple-darwin21.3.0)

設定方法

.zshrc などに以下を記述します。

zshaddhistory() {
    [[ "$?" == 0 ]]
}

設定自体は 【Zsh】コマンド履歴にエラーの履歴を残さない設定 の通りです。

zshaddhistory はフック関数です。
0 を返せば実行コマンドは保存されます。
1 を返せば次のコマンドが実行されるまでは履歴に残りますが保存されません。失敗したコマンドを修正して再利用する分には困らないということですね。
zsh: 9 Functions

$? でコマンドの終了ステータスをみて、成功であれば保存し、失敗であれば保存しないようになっています。

上手く動かない(保存されてしまう)

ところが、自分の環境では失敗したコマンドも保存されてしまっていました。
履歴に関する設定がおかしいのでは...?と、調べていたところ、↓ のオプションが問題でした。

setopt inc_append_history

これは、シェルの終了を待たずに実行コマンドをただちに履歴ファイルに書き込むオプションです。
zsh: 16 Options#History

このオプションは、別タブや別パネで実行したコマンドをすぐに呼び出したい時に有用だったのですが、 zshaddhistory フック関数で先述のように書いても効かなくなってしまう副作用がありました。

このオプションは無効にし、存在しないコマンドを実行した後に history を呼び出したら、失敗したコマンドは保存されなくなったことを確認しました。

ただし、 inc_append_history を無効にしてしまった後は、セッションを終了するまでは履歴が共有されなくなってしまうため、代わりに

setopt share_history

を有効にしました。
これで今の利便性を維持したまま、目的を達成することができました。

めでたし めでたし

終わりに

参考も兼ねて、現在の私の history 周りの設定を載せておきます。

setopt hist_ignore_all_dups             # 重複を記録しない
setopt hist_ignore_space                # スペース始まりのコマンドは記録しない
setopt hist_reduce_blanks               # 余分なスペース排除
setopt hist_verify                      # historyから実行時に確認
setopt share_history                    # 履歴ファイルを共有
setopt extended_history                 # zshの開始終了を記録

Discussion