一定時間後に .zsh_history を自動的に削除する最適な方法は何ですか?

一定時間後に .zsh_history を自動的に削除する最適な方法は何ですか?

あるような気がするZSH セットアップオプションなし.zsh_history一定期間経過後(例えば、今から 1 か月以上経過後)に自動的に削除されるようにします。これを実現するための最も簡単なハックは何でしょうか?

答え1

正解です。 には時間ベースの有効期限オプションはありません.zsh_history。おそらく、あらゆる種類の時間指定の有効期限にはEXTENDED_HISTORY形式 (各コマンドの開始時刻を含む) が必要であり、 はEXTENDED_HISTORY新しい (より新しい) 機能 (少なくともほとんどの有効期限オプションよりも新しい) であるためです。

また、zsh の機能は「時間」というあいまいな概念とあまり良い関係にありません。時間ベースのグロブ フラグの制限を読んでみれば、そのことがわかります。

アクセス時間と現在の部分の差の小数部分は、適切な単位では比較時に無視されます。たとえば、はecho *(ah-5)過去 5 時間以内にアクセスされたファイルをエコーし​​ますが、はecho *(ah+5)少なくとも 6 時間前にアクセスされたファイルをエコーし​​ます。厳密に 5 時間から 6 時間の間の時間は 5 時間として扱われるためです。

さらに、重複削除オプションのいずれかをオンにしている場合は、zshは削除します。年上の最新のエントリが優先されるため、「古い」エントリのリストは常に変化し、時間ベースの有効期限が難しくなります。

LSerni が言うように、自分で解析したい場合は、おそらく自分で解析するのが最善の選択肢です。その場合の注意点の 1 つは、履歴内の複数行のエントリが逐語的に、つまり複数行に書き込まれることです。そのため、一部の行は履歴エントリではなく継続であるため、単純に「行ごとに」解析することはできません。

もう一つの心配は、おそらく本当にこれを行う安全な方法は、zshの履歴管理と直接統合することだけです。なぜなら、履歴ファイルを変更する外部のコードは、実行中のインスタンスからの干渉(または干渉)の危険に常にさらされているからですzsh。つまり、bashありえないブートまたはシャットダウン プロセスのシングル ユーザー部分中など、ログインする必要があります。

このPythonコードは、履歴を新しいファイルにコピーし、そこから読み取り、カットオフ日を渡すエントリを違う新しいファイル。宛先ファイルを変更して.zsh_history元のファイルを上書きすることもできますが、発生する可能性のあるファイルの破損については一切責任を負いません。

より古いエントリはCUTOFF削除されます (例では 7 日間を使用しましたが、簡単にまたは1 か月7に変更できます)。これは作業ディレクトリとして で実行されていると想定されています。3031$HOME

これはまた、履歴が時間順にソートされていることを前提としていますが、この仮定がどの程度安全かはわかりません。(もしそうでない場合、最初のエントリのタイムスタンプに達すると、意図したよりも多くのエントリが保持される可能性があります。カットオフ時間を超えると、それ以降のすべてが含まれます。そのため、最初の新しいエントリの後に来る古いエントリは、誤って保存されます。これは、意図しないものが削除される可能性よりも、優先されるべき正しい種類の誤った出力のようです。

#!/usr/bin/python3

import shutil
import time
from itertools import dropwhile

CUTOFF = time.time() - (86400 * 7)  # one week ago

hist = []
shutil.copy2(".zsh_history", ".zsh_history.bak")
with open(".zsh_history.bak", "rb") as f:
    for l in f.readlines():
        if l.startswith(b': '):
            # Start of a new history entry
            # Add a new tuple (time, history_line) to the list
            ts = int(l.split(b':')[1])
            hist.append((ts, l))
            continue
        # Continuation line, append it to the previous entry
        prev = hist.pop()
        hist.append((prev[0], b''.join([prev[1], l])))

with open(".zsh_history.new", "wb") as f:
    # Drop list entries while timestamp < CUTOFF,
    # Then write contents of each remaining entry to file
    for l in dropwhile(lambda x: x[0] < CUTOFF, hist):
        f.write(l[1])

関連情報