2008-12-03 9 views
38

Estoy tratando de evitar que bash guarde los comandos duplicados en mi historial. Esto es lo que tengo:Impedir que los duplicados se guarden en el historial de bash

shopt -s histappend 
export HISTIGNORE='&:ls:cd ~:cd ..:[bf]g:exit:h:history' 
export HISTCONTROL=erasedups 
export PROMPT_COMMAND='history -a' 

Esto funciona bien mientras estoy inscrito y .bash_history está en la memoria. Por ejemplo:

$ history 
    1 vi .bashrc 
    2 vi .alias 
    3 cd /cygdrive 
    4 cd ~jplemme 
    5 vi .bashrc 
    6 vi .alias 

$ vi .bashrc 

$ history 
    1 vi .alias 
    2 cd /cygdrive 
    3 cd ~jplemme 
    4 vi .alias 
    5 vi .bashrc 

$ vi .alias 

$ history 
    1 cd /cygdrive 
    2 cd ~jplemme 
    3 vi .bashrc 
    4 vi .alias 

$ exit 

Pero cuando se vuelva a conectar, mi archivo de la historia se parece a esto:

$ history 
    1 vi .bashrc 
    2 vi .alias 
    3 cd /cygdrive 
    4 cd ~jplemme 
    5 vi .bashrc 
    6 vi .alias 
    7 vi .bashrc 
    8 vi .alias 

¿Qué estoy haciendo mal?

EDITAR: Eliminar las líneas shopt y PROMPT_COMMAND de .bashrc no soluciona el problema.

+1

¿Alguna vez resolvió esto? Mi/etc/profile se ve así (en un mac) y tengo el mismo problema: # http://blog.macromates.com/2008/working-with-history-in-bash/ # http: //www.ducea.com/2006/05/15/linux-tips-take-control-of-your-bash_history/ HISTCONTROL exportación = erasedups exportación HISTTIMEFORMAT HISTSIZE = 10000 exportación = "% F-% T% t" shopt -s histappend (Tratando de dar formato a este medio decente, no es fácil) – joedevon

+0

Ver esta pregunta http://unix.stackexchange.com/questions/48713/how-can-i-remove-duplicates -in-my-bash-history-preservar-orden – Nathan

+1

Este es un problema inherente a la programación y está relacionado con herramientas específicas que los programadores utilizan. Estoy desconcertado de que esta pregunta sea considerada "fuera de tema" (mucho más por al menos 5 personas). Un .bash_history redundante es una molestia de larga data para mí ahora resuelto. Sin embargo, esta pregunta podría moverse al sitio stackexchange de Unix. –

Respuesta

5
export HISTCONTROL=ignoreboth 
7

El problema es sin duda la histappend. Probado y confirmado en mi sistema.

Mi entorno relevante es:

$ set | grep HIST 
HISTFILE=/Users/hop/.bash_history 
HISTFILESIZE=500 
HISTIGNORE=' *:&:?:??' 
HISTSIZE=500 
$ export HISTCONTROL=erasedups 
$ shopt | grep hist 
cmdhist   on 
histappend  off 
histreedit  off 
histverify  off 
lithist   off 

Ahora que lo pienso, el problema es probablemente con la history -a. history -w debe escribir el historial actual sin ningún duplicado, así que úselo si no le importan los problemas de concurrencia.

2

Esto es lo que yo uso ..

[[email protected] ~]$ grep HIST .alias* 
.alias:HISTCONTROL="erasedups" 
.alias:HISTSIZE=20000 
.alias:HISTIGNORE=ls:ll:"ls -altr":"ls -alt":la:l:pwd:exit:mc:su:df:clear:ps:h:history:"ls -al" 
.alias:export HISTCONTROL HISTSIZE HISTIGNORE 
[[email protected] ~]$ 

y trabajando

[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ history | grep pwd | wc -l 
     1 
+2

Gracias Venu. El problema que estoy teniendo es un poco diferente. Digamos que hay 20 "ls" en la historia. Al escribir "ls", elimina los duplicados para que su historial sea más corto ... al menos durante la sesión. Pero salga e inicie una nueva sesión y guarda las cosas nuevas y conserva los duplicados anteriores. Deshacer la mayor parte de la utilidad de los borrados. #Facepalm. – joedevon

+0

Agregué algo muy similar a mi .bash_profile: 'export HISTIGNORE = ls:" ls -la ":" cd .. ":" cd ~ ": pwd: exit: su:" sudo -i ": clear: ps: "ps $ export HISTSIZE = 20000 export HISTCONTROL =" erasedups "' – humbolight

1

dentro de su .bash_profile añadir

alias hist="history -a && hist.py" 

a continuación, poner esto en su trayectoria como hist.py y hacerlo ejecutable

#!/usr/bin/env python 
f = open('/Users/joe/.bash_history') 
l = f.readlines() 
l.reverse() 
short = [] 
for s in l: 
    if s.rstrip() not in short: 
     short.append(s.rstrip()) 
short.reverse() 
for s in short: 
    print s 

ahora cuando se desea la lista corta sólo tiene que escribir hist

31

Por lo que yo sé, no es posible hacer lo que quiera. Veo esto como un error en el procesamiento de historial de bash que podría mejorarse.

export HISTCONTROL=ignoreboth:erasedups # no duplicate entries 
shopt -s histappend      # append history file 
export PROMPT_COMMAND="history -a"  # update histfile after every command 

Esto evitará que la memoria de la historia única, pero mientras lo hace guarda la historia de varias sesiones en el mismo archivo, no se mantiene la historia en el propio archivo único. history -a escribirá el nuevo comando en el archivo a menos que sea el mismo que el inmediatamente anterior. No hará una desduplicación completa como la configuración erasedups en la memoria.

Para ver estas tonterías en acción, inicie una nueva sesión de terminal, examine el historial y verá entradas repetidas, digamos ls. Ahora ejecute el comando ls, y todos los ls duplicados se eliminarán del historial en la memoria, dejando solo el último. El historial de memoria se hace más corto a medida que ejecuta comandos que están duplicados en el archivo de historial, pero el archivo de historial en sí continúa creciendo.

Utilizo mi propia secuencia de comandos para limpiar el archivo de historial bajo demanda.

# remove duplicates while preserving input order 
function dedup { 
    awk '! x[$0]++' [email protected] 
} 

# removes $HISTIGNORE commands from input 
function remove_histignore { 
    if [ -n "$HISTIGNORE" ]; then 
     # replace : with |, then * with .* 
     local IGNORE_PAT=`echo "$HISTIGNORE" | sed s/\:/\|/g | sed s/\*/\.\*/g` 
     # negated grep removes matches 
     grep -vx "$IGNORE_PAT" [email protected] 
    else 
     cat [email protected] 
    fi 
} 

# clean up the history file by remove duplicates and commands matching 
# $HISTIGNORE entries 
function history_cleanup { 
    local HISTFILE_SRC=~/.bash_history 
    local HISTFILE_DST=/tmp/.$USER.bash_history.clean 
    if [ -f $HISTFILE_SRC ]; then 
     \cp $HISTFILE_SRC $HISTFILE_SRC.backup 
     dedup $HISTFILE_SRC | remove_histignore >| $HISTFILE_DST 
     \mv $HISTFILE_DST $HISTFILE_SRC 
     chmod go-r $HISTFILE_SRC 
     history -c 
     history -r 
    fi 
} 

Me encantaría escuchar formas más elegantes de hacer esto.

Nota: la secuencia de comandos no funcionará si habilita la marca de tiempo en el historial a través de HISTTIMEFORMAT.

Bash puede mejorar la situación

  1. solución history -a sólo a escribir nuevos datos si no coincide con ninguna historia en la memoria, no sólo el último.
  2. deduplicar el historial cuando se leen los archivos si se establece la configuración erasedups. Un simple history -w en una nueva terminal limpiaría el archivo de historial en lugar de la escritura tonta anterior.
+3

Execellent answer. Si prefiere conservar el orden cronológico (en lugar del orden de entrada) para sus comandos, modifique 'dedup()' reemplazando 'awk ' ! x [$ 0] ++ '$ @ 'con' tac $ @ | awk'! x [$ 0] ++ '| tac'. – trusktr

+6

@raychi Solo estoy revisando para ver si esta sigue siendo la mejor solución a medida que nos acercamos a 2014 ? –

+1

Extendiendo el comentario de @trusktr, tampoco funcionaría 'history -a' para escribir datos nuevos, ya que de hecho debería eliminar la ocurrencia anterior y agregar la más reciente. Sospecho que es debido a esta complejidad que ellos ' Hemos decidido eliminar solo duplicados consecutivos. – trss

Cuestiones relacionadas