Eu sinto que existenenhuma opção de configuração ZSHpara remover automaticamente .zsh_history
após um determinado período (por exemplo, com mais de um mês a partir de agora). Qual seria o hack mais simples para conseguir isso?
Responder1
Correto, não há opções de expiração baseadas em tempo para .zsh_history
. Provavelmente porque qualquer tipo de expiração cronometrada requer o EXTENDED_HISTORY
formato (que inclui o horário de início de cada comando) e EXTENDED_HISTORY
é um recurso mais novo – mais recente que a maioria das opções de expiração, pelo menos.
Além disso, a funcionalidade zsh não tem o melhor relacionamento com o conceito confuso de "tempo" - basta ler as restrições nos sinalizadores globbing baseados em tempo para apreciar isso:
Qualquer parte fracionária da diferença entre o tempo de acesso e a parte atual nas unidades apropriadas é ignorada na comparação. Por exemplo,
echo *(ah-5)
ecoaria arquivos acessados nas últimas cinco horas, enquantoecho *(ah+5)
ecoaria arquivos acessados há pelo menos seis horas, já que tempos estritamente entre cinco e seis horas são tratados como cinco horas.
Além disso, se você tiver alguma das opções de remoção de duplicatas ativada, o zsh removerámais velhoentradas em favor da mais nova, portanto a lista de entradas "antigas" está em constante fluxo, tornando a expiração baseada no tempo mais complicada.
Se você quiser fazer isso, como diz LSerni, analisar você mesmo é provavelmente a melhor opção. Uma coisa complicada sobre isso é que as entradas de várias linhas no histórico são escritas literalmente, ou seja, em várias linhas - então você não pode analisá-las simplesmente "linha por linha" porque algumas linhas não são entradas do histórico, elas são continuações.
Minha outra preocupação é que provavelmente não háverdadeiramentemaneira segura de fazer isso, exceto integrá-lo diretamente ao gerenciamento de histórico do zsh, porque qualquer código externo que modifique o arquivo de histórico está em constante perigo de interferência (ou interferência) de uma instância em execução do zsh
. Quero dizer, a menos que você escreva algo bash
que só funcione quando vocênão é possívelestar logado, como durante as partes de usuário único dos processos de inicialização ou desligamento.
Este código Python evita esse problema copiando o histórico para um novo arquivo, lendo-o e, em seguida, gravando as entradas que passam a data limite para umdiferentenovo arquivo. O arquivo de destino pode ser alterado para .zsh_history
substituir o arquivo original, mas não assumo nenhuma responsabilidade por qualquer corrupção de arquivo que possa ocorrer.
Entradas mais antigas CUTOFF
são descartadas (usei 7 dias no exemplo, mas você pode facilmente mudar 7
para 30
ou 31
por um mês). Presume-se que isso esteja sendo executado $HOME
como diretório de trabalho.
Isso também pressupõe que o histórico seja classificado por tempo, não sei quão segura é essa suposição. (Se não for verdade, você pode acabar mantendo mais entradas do que o pretendido, porque uma vez atingido o carimbo de data e hora da primeira entradadepoiso tempo limite, tudo depois está incluído. Portanto, as entradas mais antigas que vierem depois da primeira mais recente serão preservadas acidentalmente. O que parece ser o tipo certo de resultado incorreto a ser favorecido, em vez de possivelmente descartar algo não intencional.)
#!/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])