Como excluir comandos no histórico que correspondem a uma determinada string?

13

Preciso excluir todos os comandos do meu histórico que correspondem a uma string. Eu tentei:

$ history | grep searchstring | cut -d" " -f2 | history -d
-bash: history: -d: option requires an argument

$ history | grep searchstring | cut -d" " -f2 | xargs history -d
xargs: history: No such file or directory

$ temparg() { while read i; do "$@" "$i"; done }
$ history | grep searchstring | cut -d" " -f2 | temparg history -d
(no error, but nothing is deleted)

Qual é a maneira certa de fazer isso?

linuxfix
fonte
Embora existam respostas funcionais abaixo, ainda me pergunto por que não funciona history -d X. Me deparei com essa pergunta porque tinha acabado de fazer history | grep search_str | sort -nr | awk '{print $1}' | while read i; do history -d $i; done. Nenhum erro, mas nada excluído. Alguém pode explicar o porquê?
mivk

Respostas:

18

O historycomando apenas opera no seu arquivo de histórico $HISTFILE(normalmente ~/.historyou ~/.bash_history). Será muito mais fácil se você apenas remover as linhas desse arquivo, o que pode ser feito de várias maneiras. grepé uma maneira, mas você deve tomar cuidado para não sobrescrever o arquivo enquanto ainda o lê:

$ grep -v searchstring "$HISTFILE" > /tmp/history
$ mv /tmp/history "$HISTFILE"

Outra maneira é com sed:

$ sed -i '/searchstring/d' "$HISTFILE"
Michael Mrozek
fonte
Boa resposta; $HISTFILEpoderia conter espaços, provavelmente vale a pena citá-lo.
Chris Baixo
Cuidado ... o arquivo de história é imprevisível; se você tiver muitas conchas abertas, não é possível dizer exatamente o que será salvo e em que ordem. Alguém pode confirmar que shells já abertos não reescreverão o histórico que eles carregaram na inicialização, quando fechados?
orion
8

A resposta de Michael Mrozek funcionará se você não se importar em remover comandos da sessão atual. Se fizer isso, você deve gravar no arquivo de histórico antes de executar as operações em sua postagem history -a.

Além disso, depois de remover as entradas que deseja do seu arquivo de histórico, você pode recarregá-lo emitindo e history -c, em seguida history -r.

Chris Down
fonte
2

Com base nas respostas de Michael e Chris , criei o seguinte. Adicione-o ao seu ~/.bashrcarquivo e carregue-o com . ~/.bashrcou source ~/.bashrc.

:<<COMMENT
    Deletes all lines from the history that match a search string, with a
    prompt. The history file is then reloaded into memory.

    Examples
        hxf "rm -rf"
        hxf ^source

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#The unalias prevents odd errors when calling". ~/.bashrc" (May result in
#"not found" errors. That's okay).
unalias hxf
hxf()  {
    read -r -p "About to delete all items from history that match \"$1\". Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        #Delete all matched items from the file, and duplicate it to a temp
        #location.
        echo -e "grep -v \"$1\" \"$HISTFILE\" > /tmp/history"
        grep -v "$1" "$HISTFILE" > /tmp/history

        #Clear all items in the current sessions history (in memory). This
        #empties out $HISTFILE.
        echo "history -c"
        history -c

        #Overwrite the actual history file with the temp one.
        echo -e "mv /tmp/history \"$HISTFILE\""
        mv /tmp/history "$HISTFILE"

        #Now reload it.
        echo -e "history -r \"$HISTFILE\""
        history -r "$HISTFILE"     #Alternative: exec bash
    else
        echo "Cancelled."
    fi
}
aliteralmind
fonte
2

Para quem procura uma linha:

while history -d $(history | grep 'SEARCH_STRING_GOES_HERE'| head -n 1 | awk {'print $1'}) ; do :; history -w; done

Então, se você quisesse, por exemplo. exclua várias linhas com uma senha, simplesmente substitua "SEARCH_STRING_GOES_HERE" pela senha. Isso pesquisará todo o seu histórico por essa sequência de pesquisa e a excluirá.

2 coisas para estar ciente

  • grep usa regex, a menos que você forneça -F como argumento
  • O comando mostrará 1 erro, quando não houver mais correspondências. Ignore isto.
thelogix
fonte
Eu recebi um erro (-bash: history: -d: option requer um argumento), mas ainda funcionou?
Paradroid 15/01/19
Ele executa o comando delete continuamente, até falhar com um erro (porque não há mais nada a ser excluído). Apenas ignore o erro.
Thelogix 17/01/19
1
cat "$HISTFILE" | grep -v "commandToDelete" >> "$HISTFILE" && exit

Isso funcionou para mim. history -c && history -a não recarregou o arquivo de histórico corretamente para mim. Então, em vez disso, saio da minha sessão logo após reescrever o arquivo de histórico, para que o que está na memória não o substitua.

Hydde87
fonte