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?


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

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.


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

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

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


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


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;)


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 .


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

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

history -d 511 520

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.


1

Tente o seguinte:

for i in {511..520}; do history -d $i; echo "history -d $i"; done

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.


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


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.


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`

0

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.