bash 履歴に重複が保存されないようにする [closed] 質問する

bash 履歴に重複が保存されないようにする [closed] 質問する

bash重複したコマンドが履歴に保存されるのを防ごうとしています。 次のような結果になりました:

shopt -s histappend
export HISTIGNORE='&:ls:cd ~:cd ..:[bf]g:exit:h:history'
export HISTCONTROL=erasedups
export PROMPT_COMMAND='history -a'

これは、ログインして.bash_historyメモリ内にある間は正常に動作します。例:

$ history
    1 vi .bashrc
    2 vi .alias
    3 cd /cygdrive
    4 cd ~jplemme
    5 vi .bashrc
    6 vi .alias

$ vi .bashrc

$ history
    1 vi .alias
    2 cd /cygdrive
    3 cd ~jplemme
    4 vi .alias
    5 vi .bashrc

$ vi .alias

$ history
    1 cd /cygdrive
    2 cd ~jplemme
    3 vi .bashrc
    4 vi .alias

$ exit

しかし、再度ログインすると、履歴ファイルは次のようになります。

$ history
    1 vi .bashrc
    2 vi .alias
    3 cd /cygdrive
    4 cd ~jplemme
    5 vi .bashrc
    6 vi .alias
    7 vi .bashrc
    8 vi .alias

何が間違っているのでしょうか?

編集:から行をshopt削除しても問題は解決しません。PROMPT_COMMAND.bashrc

ベストアンサー1

私の知る限り、あなたが望むことを行うことはできません。これは bash の履歴処理のバグであり、改善の余地があると思います。

export HISTCONTROL=ignoreboth:erasedups   # no duplicate entries
shopt -s histappend                       # append history file
export PROMPT_COMMAND="history -a"        # update histfile after every command

これにより、メモリ内の履歴は一意に保たれますが、複数のセッションの履歴が同じファイルに保存される一方で、ファイル自体の履歴は一意に保たれません。は、直前のコマンドと同じでない限り、新しいコマンドをファイルに書き込みます。メモリ内の設定のhistory -aように、完全な重複排除は実行されません。erasedups

この馬鹿げた動作を実際に確認するには、新しいターミナル セッションを開始し、履歴を調べると、 などの重複エントリが表示されますls。ここでlsコマンドを実行すると、重複したものはすべてlsメモリ内の履歴から削除され、最後の 1 つだけが残ります。履歴ファイルに重複しているコマンドを実行すると、メモリ内の履歴は短くなりますが、履歴ファイル自体は大きくなり続けます。

独自のスクリプトを使用して、必要に応じて履歴ファイルをクリーンアップします。

# remove duplicates while preserving input order
function dedup {
   awk '! x[$0]++' $@
}

# removes $HISTIGNORE commands from input
function remove_histignore {
   if [ -n "$HISTIGNORE" ]; then
      # replace : with |, then * with .*
      local IGNORE_PAT=`echo "$HISTIGNORE" | sed s/\:/\|/g | sed s/\*/\.\*/g`
      # negated grep removes matches
      grep -vx "$IGNORE_PAT" $@
   else
      cat $@
   fi
}

# clean up the history file by remove duplicates and commands matching
# $HISTIGNORE entries
function history_cleanup {
   local HISTFILE_SRC=~/.bash_history
   local HISTFILE_DST=/tmp/.$USER.bash_history.clean
   if [ -f $HISTFILE_SRC ]; then
      \cp $HISTFILE_SRC $HISTFILE_SRC.backup
      dedup $HISTFILE_SRC | remove_histignore >| $HISTFILE_DST
      \mv $HISTFILE_DST $HISTFILE_SRC
      chmod go-r $HISTFILE_SRC
      history -c
      history -r
   fi
}

これをもっとエレガントに行う方法を聞きたいです。

注意: HISTTIMEFORMAT を介して履歴のタイムスタンプを有効にすると、スクリプトは機能しません。

Bashは状況を改善できる

  1. history -a最後のデータだけでなく、メモリ内のどの履歴とも一致しない場合にのみ新しいデータを書き込むように修正しました。
  2. erasedups設定がされている場合、ファイルの読み取り時に履歴の重複を排除します。history -w新しいターミナルで単純な操作を行うと、上記の愚かなスクリプトの代わりに履歴ファイルがクリーンアップされます。

おすすめ記事