Як видалити команди з історії, що відповідають заданому рядку?


14

Мені потрібно видалити всі команди в моїй історії, що відповідають рядку. Я спробував:

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

Який правильний спосіб це зробити?


1
Хоча нижче є робочі відповіді, мені все ще цікаво, чому це не працює history -d X. Я натрапив на це питання, тому що я щойно зробив history | grep search_str | sort -nr | awk '{print $1}' | while read i; do history -d $i; done. Немає помилок, але нічого не видалено. Хтось може пояснити, чому?
mivk

Відповіді:


19

historyКоманда просто працює на файл історії, $HISTFILE(зазвичай ~/.historyабо ~/.bash_history). Буде набагато простіше, якщо ви просто видалите рядки з цього файлу, що можна зробити багатьма способами. grepце один із способів, але ви повинні бути обережними, щоб не перезаписати файл під час його читання:

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

Ще один спосіб sed:

$ sed -i '/searchstring/d' "$HISTFILE"

Гарна відповідь; $HISTFILEможе містити пробіли, ймовірно, варто його цитувати.
Кріс Даун

Обережно ... історіфіл непередбачуваний, якщо у вас багато відкритих оболонок, це не говорить про те, що саме врятується і в якому порядку. Чи може хтось підтвердити, що вже відкриті оболонки не перепишуть історію, яку вони завантажували при ініціалізації, коли закриваються?
Оріон

8

Відповідь Майкла Мрозека спрацює, якщо вам не байдуже видалення команд із поточного сеансу. Якщо ви це зробите, вам слід записатись у файл історії, перш ніж робити операції на його посаді, виконуючи history -a.

Крім того, після вилучення потрібних записів із історіального файлу ви можете перезавантажити, видавши history -c, потім history -r.


3

Для тих, хто шукає однолінійку:

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

Отже, якщо ви хотіли, наприклад. видаліть кілька рядків із паролем, просто замініть "SEARCH_STRING_GOES_HERE" паролем. Це здійснить пошук у всій історії за цим рядком пошуку та видалить його.

2 речі, які слід пам’ятати

  • grep використовує регулярний вираз, якщо ви не вводите аргумент -F
  • Команда покаже 1 помилку, як тільки більше не буде збігів. Ігноруйте це.

У мене з’явилася помилка (-bash: history: -d: option вимагає аргументу), але вона все одно спрацювала?
парадороїд

1
Вона виконує команду delete постійно, поки не виходить з помилки (тому що більше нічого не можна видаляти). Просто ігноруйте помилку.
thelogix

Це не тільки он-лайн, але і правильна проста відповідь. Так , не плутайте про history: -d: option requires an argumentпомилку! Це в кінці циклу while = = очікуване - воно працює, а потім каже: "Я нічого іншого не можу знайти!" :)
jave.web

2

Спираючись на відповіді Майкла та Кріса , я придумав наступне. Додайте його у свій ~/.bashrcфайл, а потім завантажте його . ~/.bashrcабо 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
}

1
cat "$HISTFILE" | grep -v "commandToDelete" >> "$HISTFILE" && exit

Це працювало для мене. історія -c && history - не завантажив файл історії для мене належним чином. Тож замість цього я просто виходжу з сеансу відразу після переписування файла історії, щоб той, що запам'ятовується, не перезаписав його.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.