web-dev-qa-db-ja.com

特定の文字列に一致する履歴内のコマンドを削除する方法は?

文字列に一致する履歴内のすべてのコマンドを削除する必要があります。私はもう試した:

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

これを行う正しい方法は何ですか?

14
linuxfix

historyコマンドは履歴ファイル$HISTFILE(通常~/.historyまたは~/.bash_history)を操作するだけです。そのファイルから行を削除するだけの方がはるかに簡単です。これはさまざまな方法で実行できます。 grepは1つの方法ですが、読み取り中にファイルを上書きしないように注意する必要があります。

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

もう1つの方法は、sedを使用することです。

$ sed -i '/searchstring/d' "$HISTFILE"
19
Michael Mrozek

現在のセッションからコマンドを削除する必要がない場合は、Michael Mrozekの回答が機能します。その場合、彼の投稿でhistory -aを実行して操作を行う前に、履歴ファイルに書き込む必要があります。

また、履歴ファイルから必要なエントリを削除した後、history -cを発行し、次にhistory -rを発行することで、エントリを再ロードできます。

8
Chris Down

ワンライナーをお探しの方:

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

だから、例えばしたい場合。パスワードが含まれている複数の行を削除するには、単に「SEARCH_STRING_GOES_HERE」をパスワードに置き換えます。これにより、履歴全体からその検索文字列が検索され、削除されます。

注意すべき2つのこと

  • 引数として-Fを指定しない限り、grepは正規表現を使用します
  • 一致するものがなくなると、コマンドは1つのエラーを表示します。それを無視します。
3
thelogix

Michael および Chris ' の回答に基づいて、次のことを考え出しました。それを~/.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
}
2
aliteralmind
cat "$HISTFILE" | grep -v "commandToDelete" >> "$HISTFILE" && exit

これでうまくいきました。 history -c && history -aが履歴ファイルを適切に再ロードしませんでした。代わりに、履歴ファイルを書き換えた直後にセッションを終了するだけなので、メモリ内のファイルによって上書きされません。

1
Hydde87