Jak usunąć historię ostatnich 10 poleceń w powłoce?

133

Następują polecenia

  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

Mogę usunąć pojedyncze przez history -d 511, ale jak usunąć ostatnie 10 poleceń i między 10 historią poleceń za pomocą pojedynczego polecenia w powłoce?

Czy możemy napisać skrypt bash i wykonać go w celu usunięcia historii?

Justin John
źródło
18
vi $HISTFILEi usuń to, co chcesz. Użyj, head -n -10jeśli musisz to zautomatyzować.
Anton Kovalenko,
Czy to pytanie jest nie na temat ? lub To nie jest dobre miejsce do zadawania tego rodzaju pytań? Jeśli tak, to gdzie mam zadać to pytanie, czyli gdzie w wymianie stosów?
Justin John,
1
Polecenia powłoki działają tak samo, niezależnie od tego, czy jesteś zalogowany lokalnie, czy przez ssh.
Barmar,
2
Unix i Linux StackExchange (unix.stackexchange.com) to prawdopodobnie lepsze miejsce na to pytanie. To jest poza tematem, ponieważ nie odnosi się ściśle do programowania.
Dan Molding
4
Programowanie skryptu powłoki jest idealnym rozwiązaniem tego pytania, dlatego należy je traktować jako związane z programowaniem. Nie wspominając o tym, że OP faktycznie poprosił specjalnie o skrypt.
SSH To

Odpowiedzi:

112

Czy próbowałeś edytować plik historii bezpośrednio:

~/.bash_history
WheretheresaWill
źródło
2
@WherethereisaWill OP chciał skryptu, a nie ręcznego plug and chug.
Tyler Jandreau,
12
zacznie obowiązywać po ponownym uruchomieniu (zamknięciu i ponownym otwarciu) terminala
khaled_webdev
8
Jeśli zrobisz to z vimem, możesz znaleźć swoją historię usuwania, ~/.viminfowięc pamiętaj, aby ją usunąć!
drewno walcowe
5
czasami jest to przechowywane w pamięci i żadna ręczna edycja nie zostanie utrwalona po następnym zalogowaniu ..
superbohater
5
@FizerKhan Mam na myśli to, że zmiany wprowadzone w .bash_historymogą zostać nadpisane przez to, co jest w pamięci. To rozwiązanie okazało się pomocne: superuser.com/a/384383/253543
superbohater
75

Moja odpowiedź jest oparta na poprzednich odpowiedziach, ale z dodatkiem odwrócenia kolejności, tak aby pozycje historii były usuwane od najnowszych do najświeższych.

Pobierz swoją aktualną historię (dostosuj liczbę wierszy, które chcesz zobaczyć):

history | tail -n 10

To daje mi coś takiego

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"

Wybierz pozycję początkową i końcową dla elementów, które chcesz usunąć. Skasuję wpisy od 1006 do 1008.

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

Spowoduje to wygenerowanie history -dpoleceń dla 1006, następnie 1007 stanie się 1006 i 1006 zostanie usunięte, a następnie 1008 (stało się 1007) to teraz 1006 i zostanie usunięte.

Jeśli chciałem również usunąć polecenie usuwania historii, jest to nieco bardziej skomplikowane, ponieważ musisz znać aktualny wpis historii max.

Możesz to uzyskać za pomocą (może być lepszy sposób):

history 1 | awk '{print $1}'

Łącząc to razem, możesz użyć tego do usunięcia zakresu, a także usunięcia polecenia usuwania historii:

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

Podsumuj to wszystko w funkcji, aby dodać do ~/.bashrc:

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

Przykład usunięcia polecenia 4, 5 i 6 (1049-1051) i ukrycia dowodów:

[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

Właściwie chodziło o usunięcie ostatnich 10 poleceń z historii, więc jeśli chcesz zaoszczędzić trochę wysiłku, możesz użyć innej funkcji, aby wywołać histdelfunkcję, która wykonuje obliczenia za Ciebie.

histdeln(){

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

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

Ta funkcja przyjmuje 1 argument, liczbę poprzednich elementów historii do usunięcia. Aby usunąć ostatnie 10 poleceń z historii, po prostu użyj histdeln 10.

JGC
źródło
history | tail -1 | awk '{print $1}'można uprościć dohistory 1 | awk '{print $1}'
George Hilliard
-bash: tac: command not foundw systemie Mac OSX, w przeciwnym razie byłaby to najlepsza odpowiedź.
Zim
for h in $(seq 1006 1008); do history -d 1006; doneto działa w ubuntu 16.04
mahfuz
Krótko, ale słodko:for i in {1..10}; do history -d $(($HISTCMD-11)); done
alchemia
31
for x in `seq $1 $2`
do
  history -d $1
done
Barmar
źródło
3
Pamiętaj, aby użyć wyższego numeru jako pierwszego argumentu lub usuniesz każde inne polecenie. Np. Po usunięciu polecenia 511 wszystko przesuwa się w dół, więc 512 staje się nowym 511, a 513 nowym 512. W związku z tym history -d 511działa zgodnie z oczekiwaniami, a następnie history -d 512usuwa to, co było wcześniej 513, a 512 pozostaje w historii jako polecenie 511. Mam nadzieję, że to ma sens .
Mateusz
5
@Matthew To nie jest konieczne. Nie usuwam za $xkażdym razem w pętli, usuwam $1. Więc najpierw usuwa 511, a 512 staje się 511. Następnie ponownie 511 i tak dalej.
Barmar
@Matthew Zauważ, że zrobiłem podobny komentarz do odpowiedzi Tylera. Wymyśliłem rozwiązanie, aby to naprawić.
Barmar
masz rację, w moim pośpiechu, kiedy napisałem to w jednej linii w moim poleceniu bash, którego użyłem for i in... history -d $ii otrzymałem wyniki, które opisałem w moim komentarzu powyżej. Użycie 1 $ jest absolutnie poprawne, jak podano w oryginalnej odpowiedzi.
Matthew,
21

Najpierw wpisz: historyi zapisz sekwencję numerów linii, które chcesz usunąć.

Aby wyczyścić linie z, powiedzmy, linii 1800 do 1815, napisz w terminalu:

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

Jeśli chcesz usunąć historię dla polecenia usunięcia, dodaj +1 dla 1815 = 1816, a historia dla tej sekwencji + polecenie usunięcia zostanie usunięte.

Na przykład :

$ for line in $(seq 1800 1816) ; do history -d 1800; done
Ghassan Zein
źródło
Zrobiłem aktualizację, ale nadal nie działa poprawnie w Ubuntu 12.04 .. :( Wygląda na to, że numer linii nie działa poprawnie
Binod Kalathil
Odrzuciłem sugerowaną edycję Binoda, ponieważ nie jest to błąd logiczny. Oryginalny kod Ghassana wykorzystuje to samo podejście, co odpowiedź Barmara - co działa. Komentarze do odpowiedzi Barmara wyjaśniają, dlaczego sugestia zastąpienia 1800 linią 1800 $lineusuwa co drugą linię, a następnie przekracza pożądany zakres.
Anthony Geoghegan
19

Dzięki Bash 5 możesz teraz zrobić zakres ... Brawo !:

history -d 511-520

lub licząc wstecz 10:

history -d -10--1

Fragment strony Bash 5 Man :

'historia'

Opcje, jeśli zostały dostarczone, mają następujące znaczenie:

-d PRZESUNIĘCIE Usuń wpis historii na pozycji PRZESUNIĘCIE. Jeśli PRZESUNIĘCIE jest dodatnie, należy je określić tak, jak pojawia się podczas wyświetlania historii. Jeśli PRZESUNIĘCIE jest ujemne, jest interpretowane jako względne do jednego większego niż ostatnia pozycja w historii, więc ujemne indeksy liczą się od końca historii, a indeks „-1” odnosi się do bieżącego polecenia „historia -d”.

„-d START-END” Usuwa wpisy historii między pozycjami START i END włącznie. Dodatnie i ujemne wartości START i END są interpretowane w sposób opisany powyżej.

Oto moje rozwiązanie dla Bash 4. Iteracyjnie usuwa pojedynczy wpis lub zakres historii zaczynając od najniższego indeksu.

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

delHistory 511 520
David Hatch
źródło
16

Łączenie odpowiedzi z góry:

history -w vi ~/.bash_history history -r

Bryant Bernstein
źródło
9

edytować:

Zmieniono iteratory z usztywnieniem, dobry wynik. Wywołaj również tę funkcję z odwrotnym iteratorem.

Prawdopodobnie możesz zrobić coś takiego:

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

Gdzie przywołasz w ten sposób:

./nameOfYourScript 563 514

Zauważ, że nie wprowadziłem żadnego błędu sprawdzania granic. Zostawię to jako ćwiczenie dla czytelnika.

zobacz także to pytanie

Tyler Jandreau
źródło
6
Po usunięciu 510, 511 staje się 510, 512 staje się 511 i tak dalej. Więc to usunie każdą inną linię.
Barmar,
Nie można uwzględniać zmiennych w rozwinięciach nawiasów.
chepner,
seq 563 514nic nie wydrukuje. Potrzebujesz seq 563 -1 514. Alternatywnie możesz po prostu użyć history -d $1z argumentami jako514 563
anishsane
9

Może się komuś przyda.
Kiedy logujesz się do dowolnego użytkownika dowolnej konsoli / terminala, historia twojej bieżącej sesji istnieje tylko w jakimś "buforze", który jest opróżniany do ~ / .bash_history przy twoim wylogowaniu.
Tak więc, aby zachować wszystko w tajemnicy, możesz po prostu:
history -r && exit
a zostaniesz wylogowany z wyczyszczoną historią sesji (i tylko);)

Alex
źródło
5

Użyłem kombinacji rozwiązań udostępnionych w tym wątku, aby usunąć ślad w historii poleceń. Najpierw sprawdziłem, gdzie jest zapisana historia poleceń z:

echo $HISTFILE

Edytowałem historię za pomocą:

vi <pathToFile>

Następnie opróżniam bufor historii bieżącej sesji z:

history -r && exit

Następnym razem, gdy wejdziesz do tej sesji, ostatnie polecenie, które zobaczysz w historii poleceń, jest ostatnim, które pozostawiłeś w pathToFile .

M. Gleria
źródło
to działa dla mnie, dla odpowiedzi z @jgc, kiedy loguję się ponownie do serwera, historia wraca, działa tylko dla tej zalogowanej sesji
Yogeshwar Tanwar
2

aby usunąć ostatnie 10 wpisów (na podstawie Twojego przykładu):

history -d 511 520
Filozof
źródło
1
W GNU bash w wersji 4.3.11 (1) usuwa to tylko pierwszą linię z listy
Gary,
1

history -c wyczyści wszystkie historie.

user6280539
źródło
1

Używam tego skryptu, aby usunąć ostatnie 10 poleceń w historii:

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

Używa $HISTCMDzmiennej środowiskowej, aby uzyskać indeks historii i używa go do usunięcia ostatnich 10 wpisów w history.

Junaid
źródło
1

Spróbuj wykonać następujące czynności:

for i in {511..520}; do history -d $i; echo "history -d $i"; done
rb1234
źródło
To zakłada, że ​​wymienił już historię i zna wszystkie dokumenty z wyprzedzeniem
Markoorn.
i nie może być ostatnią na liście historii, w przeciwnym razie: "pozycja historii poza zakresem"
devwebcl
musi to być:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl
1

Używam tego (mam 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
}

W builtin historyczęści, jak również ostatni -wjest, bo mam w miejscu odmianę słynnego mijającym historii zakładowego na zaciskach i funkcja ta pęknie bez tych elementów. Zapewniają wywołanie prawdziwego historywbudowanego basha (a nie mojego własnego opakowania) i zapisują historię do HISTFILE zaraz po usunięciu wpisów.

Jednak będzie to działać tak, jak w przypadku „normalnych” konfiguracji historii.

Powinieneś nazwać go liczbą ostatnich wpisów, które chcesz usunąć, na przykład:

histrm 10

Usunie ostatnie 10 wpisów.

ata
źródło
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;

Brutalny, ale funkcjonalny

Daddef
źródło
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}')

Jeśli chcesz usunąć 10 linii, po prostu zmień wartość N na 10.

Wasef Anwar
źródło
0

Prosta funkcja może zabić wszystko według numeru (chociaż działa na błędach)

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
źródło
0

Krótko, ale słodko: for i in {1..10}; do history -d $(($HISTCMD-11)); done

alchemia
źródło