Was ist die beste Möglichkeit, .zsh_history nach einer bestimmten Zeit automatisch zu entfernen?

Was ist die beste Möglichkeit, .zsh_history nach einer bestimmten Zeit automatisch zu entfernen?

Ich habe das Gefühl, es gibtkeine ZSH-Setup-Optionnach einer bestimmten Zeit automatisch zu entfernen .zsh_history(z. B. älter als ein Monat ab jetzt). Was wäre der einfachste Hack, um dies zu erreichen?

Antwort1

Richtig, es gibt keine zeitbasierten Ablaufoptionen für .zsh_history. Wahrscheinlich, weil jede Art von zeitbasiertem Ablauf das Format erfordert EXTENDED_HISTORY(das die Startzeit für jeden Befehl enthält) und EXTENDED_HISTORYeine neue(re) Funktion ist – zumindest neuer als die meisten Ablaufoptionen.

Darüber hinaus hat die zsh-Funktionalität nicht das beste Verhältnis zum unscharfen Konzept von „Zeit“ – lesen Sie einfach die Einschränkungen der zeitbasierten Globbing-Flags, um das zu verstehen:

Jeder Bruchteil der Differenz zwischen der Zugriffszeit und dem aktuellen Teil in den entsprechenden Einheiten wird beim Vergleich ignoriert. Beispielsweise echo *(ah-5)würde „echo“ Dateien wiedergeben, auf die innerhalb der letzten fünf Stunden zugegriffen wurde, während echo *(ah+5)„echo“ Dateien wiedergeben würde, auf die vor mindestens sechs Stunden zugegriffen wurde, da Zeiten strenggenommen zwischen fünf und sechs Stunden als fünf Stunden behandelt werden.

Wenn Sie darüber hinaus eine der Optionen zur Duplikatsentfernung aktiviert haben, entfernt zshälterEinträge zugunsten des neuesten, sodass die Liste der „alten“ Einträge einem ständigen Wandel unterliegt, was das zeitbasierte Ablaufen schwieriger macht.

Wenn Sie es tun möchten, ist es, wie LSerni sagt, wahrscheinlich die beste Option, es selbst zu analysieren. Eine knifflige Sache dabei ist, dass mehrzeilige Einträge im Verlauf wörtlich, also in mehreren Zeilen, ausgeschrieben werden. Sie können es also nicht einfach „Zeile für Zeile“ analysieren, da einige Zeilen keine Verlaufseinträge, sondern Fortsetzungen sind.

Meine andere Sorge ist, dass es wahrscheinlich keinewirklichsichere Möglichkeit, dies zu tun, außer es direkt in die Verlaufsverwaltung von zsh zu integrieren, da jeder externe Code, der die Verlaufsdatei ändert, ständig der Gefahr von Störungen durch (oder Störungen durch) eine laufende Instanz von ausgesetzt ist zsh. Ich meine, es sei denn, Sie schreiben etwas, bashdas nur ausgeführt wird, wenn Siekann unmöglichangemeldet sein, beispielsweise während der Einzelbenutzerabschnitte des Start- oder Herunterfahrvorgangs.

Dieser Python-Code umgeht dieses Problem, indem er den Verlauf in eine neue Datei kopiert, aus dieser liest und dann die Einträge, die das Stichdatum weitergeben, in eineandersneue Datei. Die Zieldatei könnte so geändert werden, dass .zsh_historydie Originaldatei überschrieben wird, aber ich übernehme keine Verantwortung für eventuell auftretende Dateibeschädigungen.

Einträge, die älter sind als, CUTOFFwerden gelöscht. (Ich habe im Beispiel 7 Tage verwendet, aber Sie können problemlos 7auf 30oder für einen Monat ändern.) Es wird davon ausgegangen, dass dies mit als Arbeitsverzeichnis 31ausgeführt wird .$HOME

Dies setzt auch voraus, dass der Verlauf nach Zeit sortiert ist. Ich weiß nicht, wie sicher diese Annahme ist. (Wenn dies nicht zutrifft, behalten Sie möglicherweise mehr Einträge als beabsichtigt, da beim ersten Eintrag mit Zeitstempelnachdie Schlusszeit, alles danach wird eingeschlossen. Ältere Einträge, die nach dem ersten neueren kommen, bleiben also versehentlich erhalten. Das scheint die richtige Art von falscher Ausgabe zu sein, die man bevorzugen sollte, anstatt möglicherweise etwas unbeabsichtigt wegzulassen.)

#!/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])

verwandte Informationen