ファイルを誤ってシェルに貼り付けると、bashの履歴に醜い意味のないエントリが大量に追加されます。それらのエントリを削除するクリーンな方法はありますか?明らかに、シェルを閉じて.bash_history
ファイルを手動で作成しますが、現在のシェルの履歴を変更するために使用できるAPIの種類があるのでしょうか?
bash-5.0-alpha
以降、history
コマンドは削除(-d
)オプションの範囲を取得するようになりました。 rastafileの回答 を参照してください。
古いバージョンの場合は、以下の回避策を実行してください。
history -d offset
builtinを使用して現在のシェルの履歴から特定の行を削除するか、history -c
を使用して履歴全体を消去できます。
引数として1つのオフセットしかとらないため、行の範囲を削除する場合は実際的ではありませんが、ループを使用して関数にラップすることができます。
rmhist() {
start=$1
end=$2
count=$(( end - start ))
while [ $count -ge 0 ] ; do
history -d $start
((count--))
done
}
rmhist first_line_to_delete last_line_to_delete
で呼び出します。 (history
の出力に基づく行番号。)
(履歴ファイルへの書き込みを強制するには、history -w
を使用します。)
コマンドプロンプトのこの1つのライナーだけが役立ちます。
for i in {1..N}; do history -d START_NUM; done
START_NUMは、履歴内のエントリの開始位置です。 Nは、削除するエントリの数です。
例:for i in {1..50}; do history -d 1030; done
history
bash組み込みコマンドも範囲をとり、現在は2020年です。
-dオフセット
位置オフセットの履歴エントリを削除します。オフセットが負の場合、それは最後の履歴位置よりも1大きいと解釈されるため、負のインデックスは履歴の最後からカウントされ、インデックス-1は現在の履歴-dコマンドを参照します。
-d開始-終了
開始位置と終了位置の間の履歴エントリを削除します。 startとendの正と負の値は、上記のように解釈されます。
コマンド自体だけが--help
で伝えない:
Options:
-c clear the history list by deleting all of the entries
-d offset delete the history entry at position OFFSET. Negative
offsets count back from the end of the history list
-a append history lines from this session to the history file
...
例えば。 history -d 2031-2034
は、一度に4行を削除します。 $HISTCMD
を使用すると、最新のN行から逆方向に削除できます。
history -w tmpfile
でエクスポートしてから、そのファイルを編集し、history -c
でクリアしてから、history -r tmpfile
で読み戻すこともできます。 。bash_historyへの書き込みはありません。
履歴から行N
を削除すると、行N+1
は位置N
に移動します。
このため、私はすべての履歴を削除したいoldest
およびnewest
履歴行を特定することを好みます。 (注:oldest
<newest
)。
たとえば、履歴行をoldest = 123
からnewest = 135
まで削除したい場合は、次のように記述します。
$ for i in {135..123}; do history -d $i ; done
私は読みやすいと思います。加えて:for
コマンドは範囲をデクリメントすることもできます...
これにより、すべての履歴リストエントリがN回逆順に削除されます。
function hd { for i in $(seq 1 $1); do history -d $(($HISTCMD-1)); done; }
これを.bashrcに追加する場合は、次を使用します。
echo "function hd { for i in $(seq 1 $1); do history -d \$((\$HISTCMD-1)); done; }">>~/.bashrc
..その後 source ~/.bashrc
bash設定をリロードします。使用:
hd <N>, where N is the number of lines to delete
機能していないが、長くて複雑な別のアプローチについては、私の別の回答を参照してください。
User2982704の答えは私にはほとんど効果がありましたが、まったくうまくいきませんでした。このような小さなバリエーションを作らなければなりませんでした。
私の履歴が1000であり、最後の50エントリを削除したいとします
start=1000
for i in {1..50}; do count=$((start-i)); history -d $count; done
この別のアプローチをあきらめる前に、私が学んだことを書き留めておきたいと思います。私の最初の答えをデバッグする際の私の難しさの一部は、現在のコマンドが含まれているため、いくつのNが最終的に何であるかがはっきりしないということです。
より明確にするために、私は今後、行番号から削除するソリューションを試みました。そして、すごい、それがいかに困難であるかについての大きな驚きです。主な問題は、履歴ルーチンがバックグラウンドで実行されているため、たとえば50を削除すると、51が1秒未満で50になることです。そこで最後から逆行を削除する機能を作ってみました。そして、10を続けて削除しようとすると、シフトダウンしてコマンドがなくなる前に約5になります。だから、転送を削除する関数を作ってみましたが、何らかの理由で1つおきにしか取得できません関数の約半分の速度で実行される履歴ルーチンと一致しています。特定の場所で睡眠を挿入することも試みました。
一時的に履歴をオフにしてみましたが、$ HISTCMDは履歴リストではなく$ HISTFILEからの合計を表示します。だから、それは可能性のあるように見えます。私の目標は、不要なコマンドの履歴をクリーンアップして、強打番号!#を記憶し、頻繁で難しいコマンドに同じコマンドを使用できるようにすることでした。
これが私が試した機能の一部です。多分誰かが改善または診断することができます:
Going from the Number to the end:
function hd2 { a=$HISTCMD; echo $a; echo $1; echo $(($a%$1)); for i in $(seq $1 $a); do echo $i; history -d $i; done; }
Deleting from the end repeatedly with sleep:
function hd3 { a=$HISTCMD; echo $a; echo $1; echo $(($a%$1)); for i in $(seq 1 $a); do history -d $HISTCMD; sleep 1; done; }
Deleting the Number repeatedly with sleep:
function hd4 { a=$HISTCMD; echo $a; echo $1; echo $(($a%$1)); for i in $(seq 1 $a); do history -d $1; sleep 1; done; }
最初のエコー変数はデバッグ用です。 %は剰余またはmodです。 $ HISTCMDは、コマンド置換を実行せず、変数として割り当てる必要があります。
新しいアイデア:以下の関数は繰り返し使用しても機能するため:
echo "function hdn { history -d \$1; }">>~/.bashrc
echo "function hdn2 { for i in $(seq 1 \$2); history -d \$1; sleep 1; done; }">>~/.bashrc
以下のコマンドで試してみましたが、うまくいきました
end=`history| awk 'END{print $1}'`
start=`history| awk 'END{print $1-10}'`
awk -v end="$end" -v start="$start" '{for(i=start;i<=end;i++){print "history -d" " " i};exit}’|sh