Comment supprimer l'historique des 10 dernières commandes dans le shell?

131

Les commandes suivent

  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

Je peux supprimer un seul par history -d 511, mais comment supprimer les 10 dernières commandes et entre 10 l'historique des commandes en utilisant une seule commande dans le shell?

Pouvons-nous écrire un script bash et l'exécuter pour la suppression de l'historique?

Justin John
la source
18
vi $HISTFILEet supprimez ce que vous voulez. À utiliser head -n -10si vous devez l'automatiser.
Anton Kovalenko
Cette question est-elle hors sujet ? ou Ce n'est pas le bon endroit pour poser ce genre de question? Si oui, où dois-je poser cette question, je veux dire où dans l'échange de pile?
Justin John
1
Les commandes Shell fonctionnent de la même manière que vous soyez connecté localement ou via ssh.
Barmar
2
Unix et Linux StackExchange (unix.stackexchange.com) est probablement un meilleur endroit pour cette question. C'est hors sujet ici car cela ne concerne pas strictement la programmation.
Dan Moulding
4
La programmation d'un script shell est la solution idéale à cette question, par conséquent elle doit être considérée comme liée à la programmation. Sans parler du fait que le PO a demandé spécifiquement un script.
SSH ce

Réponses:

109

Avez-vous essayé de modifier directement le fichier d'historique:

~/.bash_history
Où il y a une volonté
la source
2
@WherethereisaWill OP voulait un script, pas un plug and chug manuel.
Tyler Jandreau
10
prendra effet après la relance (fermeture et réouverture) du terminal
khaled_webdev
8
Si vous faites cela avec vim, vous pouvez trouver votre historique de suppression, ~/.viminfoalors assurez-vous de le supprimer également!
waltwood
5
parfois, il est conservé en mémoire et toute modification manuelle ne sera pas persistante après la prochaine connexion ..
super
5
@FizerKhan Je veux dire que les modifications apportées dans .bash_historypeuvent être écrasées par ce qui est conservé en mémoire. J'ai trouvé cette solution utile: superuser.com/a/384383/253543
superhero
73

Ma réponse est basée sur les réponses précédentes, mais avec l'ajout de l'inversion de la séquence afin que les éléments de l'historique soient supprimés du plus récent au moins récent.

Obtenez votre historique actuel (ajustez le nombre de lignes que vous souhaitez voir):

history | tail -n 10

Cela me donne quelque chose comme

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"

Sélectionnez les positions de début et de fin des éléments à supprimer. Je vais supprimer les entrées 1006 à 1008.

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

Cela générera des history -dcommandes pour 1006, puis 1007 devient 1006 et 1006 est supprimé, puis 1008 (devenu 1007) est maintenant 1006 et est supprimé.

Si je voulais également supprimer la commande de suppression d'historique, c'est un peu plus compliqué car vous devez connaître l'entrée d'historique max actuelle.

Vous pouvez l'obtenir avec (il y a peut-être un meilleur moyen):

history 1 | awk '{print $1}'

En le rassemblant, vous pouvez l'utiliser pour supprimer une plage et également supprimer la commande de suppression de l'historique:

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

Enveloppez tout cela dans une fonction à ajouter à votre ~/.bashrc:

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

Exemple de suppression des commandes 4, 5 et 6 (1049-1051) et de masquage des preuves:

[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

La question était en fait de supprimer les 10 dernières commandes de l'historique, donc si vous voulez économiser un peu d'effort, vous pouvez utiliser une autre fonction pour appeler la histdelfonction qui fait les calculs pour vous.

histdeln(){

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

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

Cette fonction prend 1 argument, le nombre d'éléments d'historique précédents à supprimer. Donc, pour supprimer les 10 dernières commandes de l'historique, utilisez simplement histdeln 10.

JGC
la source
history | tail -1 | awk '{print $1}'peut être simplifié àhistory 1 | awk '{print $1}'
George Hilliard
-bash: tac: command not foundsur Mac OSX, sinon ce serait la meilleure réponse.
Zim le
for h in $(seq 1006 1008); do history -d 1006; donecela fonctionne dans ubuntu 16.04
mahfuz
Court mais doux:for i in {1..10}; do history -d $(($HISTCMD-11)); done
alchimie le
30
for x in `seq $1 $2`
do
  history -d $1
done
Barmar
la source
3
Assurez-vous d'utiliser le nombre le plus élevé pour le premier argument ou vous supprimerez toutes les autres commandes. Par exemple, lorsque la commande 511 est supprimée, tout décale vers le bas de sorte que 512 devient le nouveau 511 et 513 est le nouveau 512. Cela history -d 511fonctionne comme prévu, puis history -d 512supprime ce qui était auparavant 513, et 512 reste dans l'historique en tant que commande 511. J'espère que cela a du sens .
Matthew
5
@Matthew Ce n'est pas nécessaire. Je ne supprime pas à $xchaque fois dans la boucle, je supprime $1. Donc, il supprime d'abord 511, et 512 devient 511. Ensuite, il supprime à nouveau 511, et ainsi de suite.
Barmar
@Matthew Remarquez que j'ai fait un commentaire similaire à la réponse de Tyler. J'ai proposé ma solution pour résoudre ce problème.
Barmar
vous avez raison, dans ma hâte quand j'ai écrit ceci en une seule ligne dans mon invite de bash, j'ai utilisé for i in... history -d $iet j'ai obtenu les résultats que j'ai décrits dans mon commentaire ci-dessus. En utilisant 1 $, c'est absolument correct, comme indiqué dans votre réponse originale.
Matthew
18

Tout d'abord, tapez: historyet notez la séquence de numéros de ligne que vous souhaitez supprimer.

Pour effacer les lignes, disons de la ligne 1800 à 1815, écrivez ce qui suit dans le terminal:

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

Si vous souhaitez supprimer l'historique de la commande de suppression, ajoutez +1 pour 1815 = 1816 et l'historique de cette séquence + la commande de suppression sera supprimée.

Par exemple :

$ for line in $(seq 1800 1816) ; do history -d 1800; done
Ghassan Zein
la source
J'ai fait une mise à jour mais ne fonctionne toujours pas correctement dans Ubuntu 12.04 .. :( Il semble que la partie du numéro de ligne ne fonctionne pas correctement
Binod Kalathil
J'ai rejeté la modification suggérée par Binod car ce n'est pas une erreur logique. Le code original de Ghassan utilise la même approche que la réponse de Barmar - ce qui fonctionne. Les commentaires à la réponse de Barmar expliquent pourquoi la suggestion de remplacer 1800 par $linesupprime toutes les deux lignes et dépasse ensuite la plage souhaitée.
Anthony Geoghegan
18

Avec Bash 5, vous pouvez maintenant faire une gamme ... Hourra!:

history -d 511-520

ou en comptant à rebours 10:

history -d -10--1

Extrait de la page de l'homme Bash 5 :

'l'histoire'

Les options, si elles sont fournies, ont les significations suivantes:

'-d OFFSET' Supprime l'entrée d'historique à la position OFFSET. Si OFFSET est positif, il doit être spécifié tel qu'il apparaît lorsque l'historique est affiché. Si OFFSET est négatif, il est interprété comme relatif à un supérieur à la dernière position de l'historique, donc les indices négatifs sont comptés à rebours à partir de la fin de l'historique, et un index de «-1» fait référence à la commande actuelle «history -d».

'-d START-END' Supprime les entrées d'historique entre les positions START et END, incluses. Les valeurs positives et négatives pour START et END sont interprétées comme décrit ci-dessus.

Voici ma solution pour Bash 4. Il supprime de manière itérative une seule entrée ou une plage d'historique commençant par l'index le plus bas.

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

delHistory 511 520
David Hatch
la source
14

Combinaison des réponses ci-dessus:

history -w vi ~/.bash_history history -r

Bryant Bernstein
la source
9

Éditer:

Changé les itérateurs renforcés, bon appel. Appelez également cette fonction avec un itérateur inverse.

Vous pouvez probablement faire quelque chose comme ceci:

#!/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

Où vous évoquez comme ceci:

./nameOfYourScript 563 514

Remarquez que je n'ai mis aucune erreur lors de la vérification des limites. Je vais laisser cela comme un exercice au lecteur.

voir aussi cette question

Tyler Jandreau
la source
6
Après avoir supprimé 510, 511 devient 510, 512 devient 511, et ainsi de suite. Donc, cela supprimera toutes les autres lignes.
Barmar
Vous ne pouvez pas inclure de variables dans les extensions d'accolades.
chepner
seq 563 514n'imprimera rien. Vous avez besoin seq 563 -1 514. Alternativement, vous pouvez simplement utiliser history -d $1avec des arguments comme514 563
anishsane
9

Ce sera peut-être utile pour quelqu'un.
Lorsque vous vous connectez à n'importe quel utilisateur de n'importe quelle console / terminal, l'historique de votre session en cours n'existe que dans un certain "tampon" qui se vide dans ~ / .bash_history lors de votre déconnexion.
Donc, pour garder les choses secrètes, vous pouvez simplement:
history -r && exit
et vous serez déconnecté avec tout l'historique de votre session (et seul) effacé;)

Alex
la source
5

J'ai utilisé une combinaison de solutions partagées dans ce fil pour effacer la trace dans l'historique des commandes. Tout d'abord, j'ai vérifié où est enregistré l'historique des commandes avec:

echo $HISTFILE

J'ai édité l'historique avec:

vi <pathToFile>

Après cela, je vide la mémoire tampon de l'historique de la session actuelle avec:

history -r && exit

La prochaine fois que vous entrerez dans cette session, la dernière commande que vous verrez dans l'historique des commandes est la dernière que vous avez laissée sur pathToFile .

M. Gleria
la source
cela fonctionne pour moi, pour la réponse de @jgc, lorsque je me reconnecte au serveur, l'historique est de retour, ne fonctionne que pour cette session connectée
Yogeshwar Tanwar
1

history -c effacera tous les historiques.

user6280539
la source
1

pour supprimer les 10 dernières entrées (selon votre exemple):

history -d 511 520
Le philosophe
la source
1
Dans GNU bash, version 4.3.11 (1), cela ne supprime que la première ligne de la liste
Gary
1

J'utilise ce script pour supprimer les 10 dernières commandes de l'histoire:

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

Il utilise l' $HISTCMDenvironnement var pour obtenir l'index de l'historique et l'utilise pour supprimer les 10 dernières entrées dans history.

Junaid
la source
1

Essayez ce qui suit:

for i in {511..520}; do history -d $i; echo "history -d $i"; done
rb1234
la source
Cela suppose qu'il a déjà répertorié l'historique et connaît tous les identifiants à l'avance
Markoorn
et il ne peut pas être le dernier de la liste de l'historique, sinon: "position de l'historique hors de portée"
devwebcl
il doit être:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl
1

J'utilise ceci (j'ai 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
}

Les builtin historyparties ainsi que la dernière -west parce que j'ai en place une variante des célèbres astuces pour partager l'histoire entre les terminaux et cette fonction serait cassée sans ces pièces. Ils assurent un appel au real bash historybuiltin (et non pas à mon propre wrapper), et à écrire l'historique dans HISTFILE juste après la suppression des entrées.

Cependant, cela fonctionnera tel quel avec les configurations d'historique "normales".

Vous devez l'appeler avec le nombre de dernières entrées que vous souhaitez supprimer, par exemple:

histrm 10

Supprime les 10 dernières entrées.

à
la source
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;

Brute mais fonctionnel

Papa
la source
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}')

Si vous souhaitez supprimer 10 lignes, changez simplement la valeur de N à 10.

Wasef Anwar
la source
0

Une fonction simple peut tout tuer par nombre (bien qu'elle barfs sur les erreurs)

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
la source
0

Court mais doux: for i in {1..10}; do history -d $(($HISTCMD-11)); done

alchimie
la source