Wie lösche ich den Verlauf der letzten 10 Befehle in der Shell?


131

Befehle folgen

  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

Ich kann einzelne löschen history -d 511, aber wie lösche ich die letzten 10 Befehle und den Verlauf zwischen 10 Befehlen mit einem einzelnen Befehl in der Shell?

Können wir ein Bash-Skript schreiben und zum Löschen des Verlaufs ausführen?


17
vi $HISTFILEund löschen Sie, was Sie wollen. Verwenden head -n -10Sie diese Option, wenn Sie sie automatisieren müssen.
Anton Kovalenko

Ist diese Frage nicht zum Thema ? oder Dies ist nicht der richtige Ort, um diese Art von Frage zu stellen? Wenn ja, wo soll ich diese Frage stellen, ich meine wo im Stapelaustausch?
Justin John

1
Shell-Befehle funktionieren gleich, unabhängig davon, ob Sie lokal oder über ssh angemeldet sind.
Barmar

2
Unix und Linux StackExchange (unix.stackexchange.com) ist wahrscheinlich ein besserer Ort für diese Frage. Es ist hier nicht zum Thema, weil es sich nicht ausschließlich auf die Programmierung bezieht.
Dan Moulding

4
Das Programmieren eines Shell-Skripts ist die ideale Lösung für diese Frage. Daher sollte es als programmierbezogen betrachtet werden. Ganz zu schweigen von der Tatsache, dass das OP tatsächlich speziell nach einem Skript gefragt hat.
SSH Dies

Antworten:


110

Haben Sie versucht, die Verlaufsdatei direkt zu bearbeiten:

~/.bash_history

2
@WherethereisaWill OP wollte ein Skript, kein manuelles Plug-and-Chug.
Tyler Jandreau

10
wird nach dem Neustart (Schließen und erneutes Öffnen) des Terminals
wirksam

8
Wenn Sie dies mit vim tun, finden Sie möglicherweise Ihren Löschverlauf in. ~/.viminfoEntfernen Sie diesen auch!
Waltwood

4
Manchmal wird es im Speicher gehalten und jede manuelle Bearbeitung wird nach dem nächsten Login nicht fortgesetzt.
Superheld

4
@FizerKhan Ich meine, dass vorgenommene Änderungen .bash_historydurch das, was im Speicher gespeichert ist, überschrieben werden können. Ich fand diese Lösung hilfreich: superuser.com/a/384383/253543
Superheld

73

Meine Antwort basiert auf vorherigen Antworten, jedoch mit der Hinzufügung einer umgekehrten Reihenfolge, sodass Verlaufselemente von den neuesten zu den letzten Nachrichten gelöscht werden.

Holen Sie sich Ihren aktuellen Verlauf (passen Sie die Anzahl der Zeilen an, die Sie sehen möchten):

history | tail -n 10

Das gibt mir so etwas wie

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"

Wählen Sie die Start- und Endpositionen für die Elemente aus, die Sie löschen möchten. Ich werde die Einträge 1006 bis 1008 löschen.

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

Dies erzeugt history -dBefehle für 1006, dann wird 1007 zu 1006 und 1006 wird gelöscht, dann ist 1008 (wurde 1007) jetzt 1006 und wird gelöscht.

Wenn ich auch den Befehl zum Löschen des Verlaufs löschen wollte, ist dies etwas komplizierter, da Sie den aktuellen Eintrag für den maximalen Verlauf kennen müssen.

Sie können dies mit bekommen (es kann einen besseren Weg geben):

history 1 | awk '{print $1}'

Wenn Sie es zusammenstellen, können Sie damit einen Bereich löschen und den Befehl zum Löschen des Verlaufs löschen:

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

Wickeln Sie dies alles in eine Funktion ein, die Sie zu Ihrem hinzufügen können ~/.bashrc:

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

Beispiel für das Löschen der Befehle 4, 5 und 6 (1049-1051) und das Ausblenden der Beweise:

[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

Die Frage war eigentlich, die letzten 10 Befehle aus dem Verlauf zu löschen. Wenn Sie also ein wenig Aufwand sparen möchten, können Sie eine andere Funktion verwenden, um die histdelFunktion aufzurufen, die die Berechnungen für Sie ausführt.

histdeln(){

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

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

Diese Funktion benötigt 1 Argument, die Anzahl der zu löschenden vorherigen Verlaufselemente. Um die letzten 10 Befehle aus dem Verlauf zu löschen, verwenden Sie einfach histdeln 10.


history | tail -1 | awk '{print $1}'kann vereinfacht werden zuhistory 1 | awk '{print $1}'
George Hilliard

-bash: tac: command not foundunter Mac OSX wäre dies sonst die beste Antwort.
Zim

for h in $(seq 1006 1008); do history -d 1006; doneDies funktioniert in Ubuntu 16.04
Mahfuz

Kurz aber fein:for i in {1..10}; do history -d $(($HISTCMD-11)); done
Alchemie

30
for x in `seq $1 $2`
do
  history -d $1
done

3
Stellen Sie sicher, dass Sie die höhere Zahl für das erste Argument verwenden, da Sie sonst jeden anderen Befehl löschen. Wenn beispielsweise der Befehl 511 gelöscht wird, verschiebt sich alles nach unten, so dass 512 zum neuen 511 und 513 zum neuen 512 wird. Daher history -d 511funktioniert es wie erwartet, history -d 512löscht dann das, was früher 513 war, und 512 bleibt als Befehl 511 in der Historie. Hoffnung, die Sinn macht .
Matthew

5
@ Matthew Das ist nicht nötig. Ich lösche nicht $xjedes Mal durch die Schleife, ich lösche $1. Also löscht es zuerst 511 und 512 wird 511. Dann löscht es wieder 511 und so weiter.
Barmar

@ Matthew Beachten Sie, dass ich einen ähnlichen Kommentar zu Tylers Antwort abgegeben habe. Ich habe meine Lösung als Lösung dafür gefunden.
Barmar

Sie haben Recht, in meiner Eile, als ich dies in einer einzigen Zeile in meiner Bash-Eingabeaufforderung schrieb, die ich verwendet habe for i in... und history -d $idie Ergebnisse erhalten habe, die ich in meinem obigen Kommentar beschrieben habe. Mit $ 1 ist dies absolut korrekt, wie in Ihrer ursprünglichen Antwort angegeben.
Matthew

18

Zuerst Typ: historyund notieren Sie die Reihenfolge der Zeilennummern Sie entfernen möchten.

Um die Zeilen von Zeile 1800 bis 1815 zu löschen, schreiben Sie Folgendes in das Terminal:

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

Wenn Sie den Verlauf für den Löschbefehl löschen möchten, fügen Sie +1 für 1815 = 1816 und den Verlauf für diese Sequenz hinzu. + Der Löschbefehl wird gelöscht.

Zum Beispiel :

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

Ich habe ein Update gemacht, aber es funktioniert immer noch nicht richtig in Ubuntu 12.04 .. :( Es sieht so aus, als ob der Zeilennummer-Teil nicht richtig funktioniert
Binod Kalathil

Ich habe Binods Änderungsvorschlag abgelehnt, da dies kein logischer Fehler ist. Ghassans Originalcode verwendet den gleichen Ansatz wie Barmars Antwort - was funktioniert. Die Kommentare zu Barmars Antwort erklären, warum der Vorschlag, 1800 durch zu ersetzen, jede zweite Zeile$line löscht und dann den gewünschten Bereich überschreitet.
Anthony Geoghegan

18

Mit Bash 5 kannst du jetzt eine Reihe machen ... Hurra!:

history -d 511-520

oder rückwärts zählen 10:

history -d -10--1

Auszug aus der Bash 5 Man Page :

'Geschichte'

Optionen haben, falls vorhanden, folgende Bedeutung:

'-d OFFSET' Löscht den Verlaufseintrag an der Position OFFSET. Wenn OFFSET positiv ist, sollte es so angegeben werden, wie es angezeigt wird, wenn der Verlauf angezeigt wird. Wenn OFFSET negativ ist, wird es als relativ zu einer Position interpretiert, die größer als die letzte Verlaufsposition ist, sodass negative Indizes ab dem Ende des Verlaufs zurückzählen und ein Index von '-1' auf den aktuellen Befehl 'history -d' verweist.

'-d START-END' Löscht die Verlaufseinträge zwischen den Positionen START und END einschließlich. Positive und negative Werte für START und END werden wie oben beschrieben interpretiert.

Hier ist meine Lösung für Bash 4. Sie löscht iterativ einen einzelnen Eintrag oder einen Verlaufsbereich, beginnend mit dem niedrigsten Index.

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

delHistory 511 520


9

bearbeiten:

Die geschweiften Iteratoren wurden geändert, guter Anruf. Rufen Sie diese Funktion auch mit einem Reverse-Iterator auf.

Sie können wahrscheinlich so etwas tun:

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

Wo Sie so hervorrufen werden:

./nameOfYourScript 563 514

Beachten Sie, dass ich keine Fehler beim Einchecken für die Grenzen eingegeben habe. Das überlasse ich dem Leser als Übung.

siehe auch diese Frage


6
Nachdem Sie 510 gelöscht haben, wird 511 zu 510, 512 wird zu 511 und so weiter. Dadurch wird jede zweite Zeile gelöscht.
Barmar

Sie können keine Variablen in Klammererweiterungen aufnehmen.
Chepper

seq 563 514druckt nichts. Du brauchst seq 563 -1 514. Alternativ können Sie einfach history -d $1mit Argumenten als514 563
anishsane

9

Vielleicht wird es für jemanden nützlich sein.
Wenn Sie sich bei einem Benutzer eines Konsolen- / Terminalverlaufs Ihrer aktuellen Sitzung anmelden, ist dieser nur in einem "Puffer" vorhanden, der beim Abmelden in ~ / .bash_history geleert wird.
Um die Dinge geheim zu halten, können Sie einfach:
history -r && exit
und Sie werden abgemeldet, wenn der gesamte (und einzige) Verlauf Ihrer Sitzung gelöscht ist;)


5

Ich habe eine Kombination von Lösungen verwendet, die in diesem Thread verwendet werden, um die Ablaufverfolgung im Befehlsverlauf zu löschen. Zuerst habe ich überprüft, wo der Befehlsverlauf gespeichert ist mit:

echo $HISTFILE

Ich habe den Verlauf bearbeitet mit:

vi <pathToFile>

Danach entleere ich den aktuellen Sitzungsverlaufspuffer mit:

history -r && exit

Wenn Sie das nächste Mal in diese Sitzung eintreten, ist der letzte Befehl, den Sie im Befehlsverlauf sehen, der letzte, den Sie in pathToFile hinterlassen haben .


Dies funktioniert für mich, für die Antwort von @jgc, wenn ich mich erneut beim Server anmelde, ist der Verlauf wieder da, funktioniert nur für die angemeldete Sitzung
Yogeshwar Tanwar


1

Ich benutze dieses Skript, um die letzten 10 Befehle im Verlauf zu löschen:

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

Es verwendet die $HISTCMDUmgebungsvariable, um den Verlaufsindex abzurufen, und verwendet diese, um die letzten 10 Einträge in zu löschen history.


1

Versuche Folgendes:

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

Das setzt voraus, dass er die Geschichte bereits aufgelistet hat und alle IDs vorher kennt
Markoorn

und es kann nicht das letzte in der Geschichtsliste sein, sonst: "Geschichtsposition außerhalb des Bereichs"
devwebcl

es muss sein:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl

1

Ich benutze dies (ich habe 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
}

Die builtin historyTeile wie auch die letzten -wsind, weil ich eine Variation der berühmten Tricks eingerichtet habe, um die Geschichte über Terminals hinweg zu teilen, und diese Funktion würde ohne diese Teile brechen. Sie sorgen für einen Anruf bei der echten Bashhistory eingebaute (und nicht mein eigener Wrapper) aufgerufen wird und der Verlauf direkt nach dem Entfernen der Einträge in HISTFILE geschrieben wird.

Dies funktioniert jedoch wie bei "normalen" Verlaufskonfigurationen.

Sie sollten es mit der Anzahl der letzten Einträge aufrufen, die Sie entfernen möchten, zum Beispiel:

histrm 10

Entfernt die letzten 10 Einträge.


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 aber funktional


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}')

Wenn Sie 10 Zeilen löschen möchten, ändern Sie einfach den Wert von N in 10.


0

Eine einfache Funktion kann alle nach Zahlen töten (obwohl sie Fehler verhindert)

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

So löschen Sie die letzten 10 Einträge (basierend auf Ihrem Beispiel):

history -d 511 520

1
In GNU Bash, Version 4.3.11 (1) löscht dies nur die erste Zeile in der Liste
Gary

0

Kurz aber süß: for i in {1..10}; do history -d $(($HISTCMD-11)); done

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.