ヒストリファイルを消してしまった!
あるとき zsh で rm ~/.zsh_history
とやってしまった時の対処方法。現在のセッションにおける history
コマンドで出てくるコマンド履歴を用いて復元を試みたときのメモ。セッションからログアウトしてしまうと使えない。
復元対象
zsh で
setopt extended_history
を設定している人向け。これで history -i -D
とすれば
39534 2018-12-25 13:55 3:34 vi
# ヒストリ番号 実行日付 実行時間 コマンド
と表示される。このとき .zsh_history の各行のフォーマットは以下のようになっている。
: 1545713738:214;vi
#: (実行時刻 unix time):(実行時間[秒]);(コマンド列)
これを復活させたい。
復元するためのコマンド
awk
などを使ってナイーブには以下のようにすれば元に戻せる。もっと効率良い方法はあるはず。
$ history -i -D -t "%s" 1 > tempHistfile.txt
$ awk '{print ": " $2}' tempHistfile.txt | sed -e "s/ $//" > dates.txt
$ awk '{c="";for(i=4;i<=NF;i++) c=c $i" "; print c}' tempHistfile.txt > commands.txt
$ awk '{print $3}' tempHistfile.txt | awk -F ':' '{print $1*60+$2}' > time.txt
$ paste -d ':' dates.txt time.txt > joined.txt
$ paste -d ';' joined.txt commands.txt > .histfile
各行説明
$ history -i -D -t "%s" 1 > tempHistfile.txt
history
の結果を最初から最後まで出力する。デフォルトでは直近のいくつかしか出力しないが、引数に1
を与えると全部出力する。-i
は実行時間を出力する。-D
は実行時刻を "YYYY-MM-DD mm:ss" 形式で出力するが、-t "%s"
オプションを追加することで unix time で出力される。
$ awk '{print ": " $2}' tempHistfile.txt | sed -e "s/ $//" > dates.txt
awk
を使って実行時刻だけを抜き出す。最終的には行頭に ": " が欲しいので、一緒に出力しておく。また行末のスペースが邪魔なので消しておく。
$ awk '{c="";for(i=4;i<=NF;i++) c=c $i" "; print c}' tempHistfile.txt > commands.txt
awk
を使ってコマンド列を抜き出す。4 要素目以降だけを抜き出すようにする。
$ awk '{print $3}' tempHistfile.txt | awk -F ':' '{print $1*60+$2}' > time.txt
awk
を使って実行時間を抜き出す。実行時刻は "mm:ss" 形式になっているので、awk -F ':'
を用いて ":" 区切りにし、第 1 要素を 60 倍したものに第 2 要素を足して秒単位に変換する。
$ paste -d ':' dates.txt time.txt > joined.txt
$ paste -d ';' joined.txt commands.txt > .histfile
それぞれ ':' 区切りと ';' 区切りで連結する。
最後に
もっとシンプルな方法があったら教えてください。あと rm
使うときは気をつけよう。