Como excluir o histórico dos últimos 10 comandos no shell?

131

Os comandos a seguir

  511  clear
  512  history
  513  history -d 505
  514  history
  515  history -d 507 510 513
  516  history
  517  history -d 509
  518  history
  519  history -d 511
  520  history

Posso excluir um por history -d 511, mas como excluir os últimos 10 comandos e entre os 10 comandos do histórico usando o comando único no shell?

Podemos escrever um script bash e executar para excluir o histórico?

Justin John
fonte
18
vi $HISTFILEe exclua o que quiser. Use head -n -10se você tiver que automatizá-lo.
Anton Kovalenko 07/02
Esta questão está fora de tópico ? ou Este não é o lugar certo para fazer esse tipo de pergunta? Se sim, onde devo fazer essa pergunta, quero dizer onde na troca de pilhas?
Justin John
1
Os comandos do shell funcionam da mesma maneira, esteja você logado localmente ou via ssh.
7283 Barmar
2
O Unix e o Linux StackExchange (unix.stackexchange.com) é provavelmente um local melhor para esta pergunta. É fora de tópico aqui porque não se relaciona estritamente à programação.
Dan Moulding
4
Programar um script de shell é a solução ideal para esta questão, consequentemente, deve ser considerado relacionado à programação. Sem mencionar o fato de que o OP realmente pediu especificamente um script.
SSH Este

Respostas:

109

Você já tentou editar o arquivo de histórico diretamente:

~/.bash_history
Onde há uma vontade
fonte
2
@WherethereisaWill OP queria um script, não um plug and chug manual.
Tyler Jandreau
10
terá efeito após relançar (fechamento e reabertura) o terminal
khaled_webdev
8
Se você fizer isso com o vim, poderá encontrar seu histórico de exclusão em, ~/.viminfoportanto, remova-o também!
21415 Waltwood
5
às vezes ele é mantido na memória e qualquer edição manual costuma ser persistiu após o próximo login ..
super-herói
5
@FizerKhan, quero dizer que as alterações feitas .bash_historypodem ser substituídas pelo que é mantido na memória. Eu encontrei esta solução útil: superuser.com/a/384383/253543
super-herói
73

Minha resposta é baseada em respostas anteriores, mas com a adição de reverter a sequência para que os itens do histórico sejam excluídos da mais recente para a menos recente.

Obtenha seu histórico atual (ajuste o número de linhas que deseja ver):

history | tail -n 10

Isso me dá algo como

1003  25-04-2016 17:54:52 echo "Command 1"
1004  25-04-2016 17:54:54 echo "Command 2"
1005  25-04-2016 17:54:57 echo "Command 3"
1006  25-04-2016 17:54:59 echo "Command 4"
1007  25-04-2016 17:55:01 echo "Command 5"
1008  25-04-2016 17:55:03 echo "Command 6"
1009  25-04-2016 17:55:07 echo "Command 7"
1010  25-04-2016 17:55:09 echo "Command 8"
1011  25-04-2016 17:55:11 echo "Command 9"
1012  25-04-2016 17:55:14 echo "Command 10"

Selecione as posições inicial e final dos itens que você deseja excluir. Vou excluir as entradas 1006 a 1008.

for h in $(seq 1006 1008); do history -d 1006; done

Isso gerará history -dcomandos para 1006, depois 1007 se tornará 1006 e 1006 será excluído, depois 1008 (se tornará 1007) agora será 1006 e será excluído.

Se eu também quis excluir o comando delete de histórico, é um pouco mais complicado, porque você precisa conhecer a entrada atual máxima do histórico.

Você pode obter isso com (pode haver uma maneira melhor):

history 1 | awk '{print $1}'

Juntando-o, você pode usá-lo para excluir um intervalo e também excluir o comando de exclusão do histórico:

for h in $(seq 1006 1008); do history -d 1006; done; history -d $(history 1 | awk '{print $1}')

Agrupe tudo isso em uma função para adicionar ao seu ~/.bashrc:

histdel(){
  for h in $(seq $1 $2); do
    history -d $1
  done
  history -d $(history 1 | awk '{print $1}')
  }

Exemplo excluindo os comandos 4, 5 e 6 (1049-1051) e ocultando a evidência:

[18:21:02 jonathag@gb-slo-svb-0221 ~]$ history 11
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:51 echo "Command 4"
 1050  25-04-2016 18:20:53 echo "Command 5"
 1051  25-04-2016 18:20:54 echo "Command 6"
 1052  25-04-2016 18:20:56 echo "Command 7"
 1053  25-04-2016 18:20:57 echo "Command 8"
 1054  25-04-2016 18:21:00 echo "Command 9"
 1055  25-04-2016 18:21:02 echo "Command 10"
 1056  25-04-2016 18:21:07 history 11
[18:21:07 jonathag@gb-slo-svb-0221 ~]$ histdel 1049 1051
[18:21:23 jonathag@gb-slo-svb-0221 ~]$ history 8
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:56 echo "Command 7"
 1050  25-04-2016 18:20:57 echo "Command 8"
 1051  25-04-2016 18:21:00 echo "Command 9"
 1052  25-04-2016 18:21:02 echo "Command 10"
 1053  25-04-2016 18:21:07 history 11

A questão era, na verdade, excluir os 10 últimos comandos do histórico; portanto, se você quiser economizar um pouco de esforço, poderá usar outra função para chamar a histdelfunção que faz os cálculos para você.

histdeln(){

  # Get the current history number
  n=$(history 1 | awk '{print $1}')

  # Call histdel with the appropriate range
  histdel $(( $n - $1 )) $(( $n - 1 ))
  }

Esta função requer 1 argumento, o número de itens do histórico anterior a serem excluídos. Então, para excluir os últimos 10 comandos do histórico, basta usar histdeln 10.

JGC
fonte
history | tail -1 | awk '{print $1}'pode ser simplificado parahistory 1 | awk '{print $1}'
George Hilliard
-bash: tac: command not foundno Mac OSX, caso contrário, essa seria a melhor resposta.
Zim
for h in $(seq 1006 1008); do history -d 1006; doneisso funciona no ubuntu 16.04
mahfuz
Curto mas doce:for i in {1..10}; do history -d $(($HISTCMD-11)); done
alquimia
30
for x in `seq $1 $2`
do
  history -d $1
done
Barmar
fonte
3
Certifique-se de usar o número mais alto para o primeiro argumento ou você excluirá todos os outros comandos. Por exemplo, quando o comando 511 é excluído, tudo muda para que 512 se torne o novo 511 e 513 é o novo 512. Portanto, history -d 511funciona conforme o esperado, history -d 512exclui o que costumava ser 513 e 512 permanece no histórico como comando 511. Espero que faça sentido .
Matthew
5
@ Matthew Isso não é necessário. Não estou excluindo $xtodas as vezes no loop, estou excluindo $1. Portanto, ele primeiro exclui 511 e 512 se torna 511. Em seguida, exclui 511 novamente e assim por diante.
Barmar
@ Matthew Observe que eu fiz um comentário semelhante à resposta de Tyler. Eu vim com minha solução como uma correção para isso.
Barmar
você está correto, na minha pressa quando escrevi isso em uma única linha no prompt do bash que eu usei for i in... history -d $ie obtive os resultados que descrevi no meu comentário acima. Usando $ 1, isso está absolutamente correto, conforme indicado na sua resposta original.
Matthew
18

Primeiro, digite: historye anote a sequência dos números de linha que você deseja remover.

Para limpar as linhas de, digamos, da linha 1800 a 1815, escreva o seguinte no terminal:

$ for line in $(seq 1800 1815) ; do history -d 1800; done

Se você deseja excluir o histórico do comando de exclusão, adicione +1 para 1815 = 1816 e o ​​histórico dessa sequência + o comando de exclusão será excluído.

Por exemplo :

$ for line in $(seq 1800 1816) ; do history -d 1800; done
Ghassan Zein
fonte
Eu fiz uma atualização, mas ainda não está funcionando corretamente no Ubuntu 12.04 .. :( Parece que a parte número da linha não está funcionando corretamente
Binod Kalathil
Rejeitei a edição sugerida por Binod, pois não é um erro lógico. O código original de Ghassan usa a mesma abordagem da resposta de Barmar - que funciona. Os comentários à resposta de Barmar explicam por que a sugestão de substituir 1800 por $lineexclui todas as outras linhas e depois excede o intervalo desejado.
Anthony Geoghegan
18

Com o Bash 5, agora você pode fazer uma série ... Viva !:

history -d 511-520

ou contando para trás 10:

history -d -10--1

Trecho do Bash 5 Man Page :

'história'

As opções, se fornecidas, têm os seguintes significados:

'-d OFFSET' Exclua a entrada do histórico na posição OFFSET. Se OFFSET for positivo, deve ser especificado como aparece quando o histórico é exibido. Se OFFSET for negativo, ele será interpretado como relativo a um maior que a última posição do histórico; portanto, os índices negativos são contados a partir do final do histórico, e um índice de '-1' refere-se ao comando 'history -d' atual.

'-d START-END' Exclui as entradas do histórico entre as posições START e END, inclusive. Valores positivos e negativos para START e END são interpretados como descrito acima.

Aqui está minha solução para o Bash 4. Exclui iterativamente uma única entrada ou um intervalo do histórico começando com o índice mais baixo.

delHistory () {
    count=$(( ${2:-$1} - $1 ))
    while [[ $count -ge 0 ]]; do
        history -d "$1"
        ((count--))
    done
}

delHistory 511 520
David Hatch
fonte
14

Combinando respostas acima:

history -w vi ~/.bash_history history -r

Bryant Bernstein
fonte
9

editar:

Mudou os iteradores apoiados, boa chamada. Além disso, chame esta função com um iterador reverso.

Você provavelmente pode fazer algo assim:

#!/bin/bash
HISTFILE=~/.bash_history   # if you are running it in a 
                           # non interactive shell history would not work else
set -o history
for i in `seq $1 $2`;
do
    history -d $i
done
history -w

Onde você evocará assim:

./nameOfYourScript 563 514

Observe que não coloquei nenhum erro ao fazer o check-in nos limites. Vou deixar isso como um exercício para o leitor.

veja também esta pergunta

Tyler Jandreau
fonte
6
Depois de excluir 510, 511 se torna 510, 512 se torna 511 e assim por diante. Portanto, isso excluirá todas as outras linhas.
7283 Barmar
Você não pode incluir variáveis ​​nas expansões de chaves.
Chepner
seq 563 514não imprimirá nada. Você precisa seq 563 -1 514. Como alternativa, você pode simplesmente usar os history -d $1argumentos como514 563
anishsane
9

Talvez seja útil para alguém.
Quando você efetua login em qualquer usuário de qualquer histórico de console / terminal da sua sessão atual, existe apenas em algum "buffer" que é direcionado para ~ / .bash_history no seu logout.
Portanto, para manter as coisas em segredo, você pode apenas:
history -r && exit
e você será desconectado com todo o histórico da sua sessão (e somente) limpo;)

Alex
fonte
5

Usei uma combinação de soluções compartilhadas neste segmento para apagar o rastreamento no histórico de comandos. Primeiro, verifiquei onde é salvo o histórico de comandos com:

echo $HISTFILE

Editei a história com:

vi <pathToFile>

Depois disso, libero o buffer do histórico da sessão atual com:

history -r && exit

Na próxima vez que você entrar nesta sessão, o último comando que você verá no histórico de comandos será o último que você deixou no pathToFile .

M. Gleria
fonte
isso funciona para mim, para a resposta do @jgc, quando eu entro novamente no servidor, o histórico está de volta, funciona apenas para a sessão logada
Yogeshwar Tanwar 17/02
1

história -c limpará todas as histórias.

user6280539
fonte
1

para excluir as últimas 10 entradas (com base no seu exemplo):

history -d 511 520
O filósofo
fonte
1
No GNU bash, versão 4.3.11 (1), isso exclui apenas a primeira linha da lista
Gary
1

Eu uso esse script para excluir os últimos 10 comandos no histórico:

pos=$HISTCMD; start=$(( $pos-11 )); end=$(( $pos-1 )); for i in $(eval echo "{${start}..${end}}"); do history -d $start; done

Ele usa $HISTCMDenvironment var para obter o índice do histórico e o usa para excluir as últimas 10 entradas history.

Junaid
fonte
1

Tente o seguinte:

for i in {511..520}; do history -d $i; echo "history -d $i"; done
rb1234
fonte
Isso pressupõe que ele já tenha listado a história e saiba todos os IDs previamente
Markoorn 15/01/19
e não pode ser o último da lista do histórico, caso contrário: "posição do histórico fora do intervalo"
devwebcl 24/09/19
deve ser:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl 24/09/19
1

Eu uso isso (tenho bash 4):

histrm() {
    local num=${1:- 1}
    builtin history -d $(builtin history | sed -rn '$s/^[^[:digit:]]+([[:digit:]]+)[^[:digit:]].*$/\1/p')
    (( num-- )) && $FUNCNAME $num
    builtin history -w
}

As builtin historypartes, assim como a última, -wé porque eu tenho uma variação dos famosos truques para compartilhar a história entre os terminais e essa função seria interrompida sem essas partes. Eles garantem uma chamada para o bash real incorporado history(e não para o meu próprio wrapper em torno dele) e escrevem o histórico para HISTFILE logo após as entradas serem removidas.

No entanto, isso funcionará como nas configurações de histórico "normal".

Você deve chamá-lo com o número de últimas entradas que deseja remover, por exemplo:

histrm 10

Irá remover as últimas 10 entradas.

ata
fonte
1
history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;

Bruto, mas funcional

Daddef
fonte
0
for h in $(seq $(history | tail -1 | awk '{print $1-N}')  $(history | tail -1 | awk '{print $1}') | tac); do history -d $h; done; history -d $(history | tail -1 | awk '{print $1}')

Se você deseja excluir 10 linhas, basta alterar o valor de N para 10.

Wasef Anwar
fonte
0

Uma função simples pode matar todos por número (embora vomite em erros)

kill_hist() {
    for i in $(echo $@ | sed -e 's/ /\n/g;' | sort -rn | sed -e 's/\n/ /;')
    do
            history -d $i;
    done
}
kill_hist `seq 511 520`
# or kill a few ranges
kill_hist `seq 1001 1010` `seq 1200 1201`
steveo'america
fonte
0

Curto, mas doce: for i in {1..10}; do history -d $(($HISTCMD-11)); done

alquimia
fonte