Jak usunąć polecenia w historii pasujące do danego ciągu?

14

Muszę usunąć wszystkie polecenia w mojej historii pasujące do ciągu. Próbowałem:

$ history | grep searchstring | cut -d" " -f2 | history -d
-bash: history: -d: option requires an argument

$ history | grep searchstring | cut -d" " -f2 | xargs history -d
xargs: history: No such file or directory

$ temparg() { while read i; do "$@" "$i"; done }
$ history | grep searchstring | cut -d" " -f2 | temparg history -d
(no error, but nothing is deleted)

Jak to zrobić?

linuxfix
źródło
1
Chociaż poniżej znajdują się działające odpowiedzi, wciąż zastanawiam się, dlaczego to nie działa history -d X. Natknąłem się na to pytanie, ponieważ właśnie to zrobiłem history | grep search_str | sort -nr | awk '{print $1}' | while read i; do history -d $i; done. Brak błędu, ale nic nie zostało usunięte. Ktoś może wyjaśnić dlaczego?
mivk

Odpowiedzi:

19

historyKomenda działa tylko na pliku historii, $HISTFILE(zazwyczaj ~/.historyalbo ~/.bash_history). O wiele łatwiej będzie po prostu usunąć linie z tego pliku, co można zrobić na wiele sposobów. grepjest jeden sposób, ale musisz uważać, aby nie nadpisać pliku podczas jego czytania:

$ grep -v searchstring "$HISTFILE" > /tmp/history
$ mv /tmp/history "$HISTFILE"

Innym sposobem jest sed:

$ sed -i '/searchstring/d' "$HISTFILE"
Michał Mrożek
źródło
Dobra odpowiedź; $HISTFILEmoże zawierać spacje, prawdopodobnie warto je zacytować.
Chris Down,
Ostrożnie ... plik histfp jest nieprzewidywalny, jeśli masz wiele otwartych powłok, nie wiadomo, co dokładnie zostanie zapisane i w jakiej kolejności. Czy ktoś może potwierdzić, że już otwarte powłoki nie będą zapisywać historii, którą załadowały podczas inicjalizacji, gdy są zamknięte?
orion
8

Odpowiedź Michała Mrożka zadziała, jeśli nie zależy ci na usuwaniu poleceń z bieżącej sesji. Jeśli to zrobisz, powinieneś napisać do pliku historii przed wykonaniem operacji w jego poście history -a.

Ponadto, po usunięciu wpisów, które chcesz z pliku historii, można przeładować go poprzez wydawanie history -c, następnie history -r.

Chris Down
źródło
3

Dla tych, którzy szukają jednej linijki:

while history -d $(history | grep 'SEARCH_STRING_GOES_HERE'| head -n 1 | awk {'print $1'}) ; do :; history -w; done

Więc jeśli chcesz np. usuń wiele wierszy z hasłem, po prostu zastąp „SEARCH_STRING_GOES_HERE” hasłem. Spowoduje to przeszukanie całej historii tego szukanego ciągu i usunięcie go.

2 rzeczy, o których należy pamiętać

  • grep używa wyrażenia regularnego, chyba że podasz -F jako argument
  • Polecenie wyświetli 1 błąd, gdy nie będzie już żadnych dopasowań. Zignoruj ​​to.
thelogix
źródło
Wystąpił błąd (-bash: historia: -d: opcja wymaga argumentu), ale nadal działa?
paradroid
1
Ciągle uruchamia polecenie usuwania, dopóki nie powiedzie się błąd (ponieważ nie ma już nic do usunięcia). Po prostu zignoruj ​​błąd.
thelogix
To nie tylko onliner, ale także właściwa prosta odpowiedź. Tak , nie mylcie się co do history: -d: option requires an argumentbłędu! Jest na KOŃCU pętli while => oczekiwano - działa, a następnie w zasadzie mówi: „Nie mogę znaleźć niczego innego!” :)
jave.web
2

Na podstawie odpowiedzi Michaela i Chrisa przedstawiłem następujące. Dodaj go do ~/.bashrcpliku, a następnie załaduj za pomocą . ~/.bashrclub source ~/.bashrc.

:<<COMMENT
    Deletes all lines from the history that match a search string, with a
    prompt. The history file is then reloaded into memory.

    Examples
        hxf "rm -rf"
        hxf ^source

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#The unalias prevents odd errors when calling". ~/.bashrc" (May result in
#"not found" errors. That's okay).
unalias hxf
hxf()  {
    read -r -p "About to delete all items from history that match \"$1\". Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        #Delete all matched items from the file, and duplicate it to a temp
        #location.
        echo -e "grep -v \"$1\" \"$HISTFILE\" > /tmp/history"
        grep -v "$1" "$HISTFILE" > /tmp/history

        #Clear all items in the current sessions history (in memory). This
        #empties out $HISTFILE.
        echo "history -c"
        history -c

        #Overwrite the actual history file with the temp one.
        echo -e "mv /tmp/history \"$HISTFILE\""
        mv /tmp/history "$HISTFILE"

        #Now reload it.
        echo -e "history -r \"$HISTFILE\""
        history -r "$HISTFILE"     #Alternative: exec bash
    else
        echo "Cancelled."
    fi
}
aliteralmind
źródło
1
cat "$HISTFILE" | grep -v "commandToDelete" >> "$HISTFILE" && exit

To zadziałało dla mnie. history -c && history -a nie przeładowałem poprawnie pliku historii. Zamiast tego kończę sesję zaraz po przepisaniu pliku historii, aby ten w pamięci go nie nadpisał.

Hydde87
źródło