BASH履歴に成功したコマンドのみを保持する


20

時々、コマンドの構文を誤解します。

# mysql -d test
mysql: unknown option '-d'
# echo $?
2

私はもう一度試して、それを正しくします:

# mysql --database test
Welcome to the MySQL monitor.
mysql >
...

エラーコードが0以外の最初のコマンドが履歴を入力するのを防ぐにはどうすればよいですか?

回答:


20

あなたが本当にそれを望んでいるとは思わない。私の通常のワークフローは次のようになります。

  • コマンドを入力します
  • それを実行します
  • 失敗したことに注意してください
  • 上キーを押す
  • コマンドを編集する
  • もう一度実行する

失敗したコマンドが履歴に保存されていないと、修正して再度実行するために簡単に戻すことができませんでした。


3
より良い設計は、セッション履歴と永続的な履歴になると思います。ありがとう!
アダムマタン

ターミナルを終了すると、履歴が保存されます。したがって、このターミナルセッションで入力したコマンドに戻ることができますが、ターミナルを終了すると、実際にはbash履歴に保存されます。
ために何

11

これを行うには、私は考えることができる唯一の方法は、使用することですhistory -dの中で$PROMPT_COMMAND。このアプローチまたはアプローチの問題は、コマンドがエラーで終了したか、ゼロ以外の終了コードで正常に完了したかを判断できないことです。

$ grep non_existent_string from_file_that_exists
$ echo $?
1

4

最後に間違ったコメントを付けて修正するのは良いことですが、その後すぐに混乱を招く可能性のあるゴミになります。

私のアプローチは2段階です。失敗したコマンドは保存し、後で削除します。

失敗したコマンドを保存する:

error_handler() {
    FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}

trap error_handler ERR

trap command signalscommandいずれかsignalsが「発生」したときに実行されます。

$(command)を実行しcommand、その出力をキャプチャします。

コマンドが失敗すると、このコードスニペットはhistory保存された最後のコマンドの履歴番号をキャプチャし、将来の削除のために変数に保存します。

シンプルな、しかしで正しく動作しないHISTCONTROLHISTIGNORE-コマンドが原因変数の一つに歴史に保存されていない場合、歴史の中に保存された最後のコマンドの履歴番号は、前のコマンドの一つです。そのため、誤ったコマンドが履歴に保存されない場合、以前のコマンドは削除されます。

少し複雑なバージョンで、その場合は正しく機能します。

debug_handler() {
    LAST_COMMAND=$BASH_COMMAND;
}

error_handler() {
    local LAST_HISTORY_ENTRY=$(history | tail -1l)

    # if last command is in history (HISTCONTROL, HISTIGNORE)...
    if [ "$LAST_COMMAND" == "$(cut -d ' ' -f 2- <<< $LAST_HISTORY_ENTRY)" ]
    then
        # ...prepend it's history number into FAILED_COMMANDS,
        # marking the command for deletion.
        FAILED_COMMANDS="$(cut -d ' ' -f 1 <<< $LAST_HISTORY_ENTRY) $FAILED_COMMANDS"
    fi
}

trap error_handler ERR
trap debug_handler DEBUG

後で保存されたコマンドを削除します。

exit_handler() {
    for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
    do
        history -d $i
    done
    FAILED_COMMANDS=
}

trap exit_handler EXIT

説明:

Bashを終了するとき、一意の履歴番号ごとに対応する履歴エントリを削除し、削除済みのコマンドから履歴番号を継承したコマンドを削除しないように
クリアFAILED_COMMANDSします。

FAILED_COMMANDS重複がないことが確かな場合は、単純に反復
(つまり、書き込みfor i in $FAILED_COMMANDS)できます。しかし、あなたはそれが(この場合には、それは常にある)最大から最小に並べ替えられないことが予想される場合は、交換してくださいuniqsort -rnu

FAILED_COMMANDSエントリを削除すると、次のコマンドの番号がシフトされるため、履歴番号は一意で、最大から最小にソートされている必要があります。を発行するとhistory -d 2、3番目のエントリが2番目になり、4番目が3番目になります。

そのため、このコードを使用する場合、格納されている最大数以下のhistory -d <n>
場所をnFAILED_COMMANDS手動で呼び出して
、コードが適切に機能することを期待することはできません。

それはおそらくフックすることをお勧めしますexit_handlerEXIT、あなたも、いつでも以前のそれを呼び出すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.