Bash command history is normally stored in $HISTFILE (in many environments, ~/.bash_history).
Sometimes you may want to edit this file directly in an editor, for example to delete a batch of unwanted history entries.
However, care is required in environments where multiple Bash sessions are open at the same time. If you simply edit $HISTFILE, your changes may later be overwritten by history held by another Bash session.
This article outlines a procedure for editing the history file as safely as possible while keeping multiple Bash sessions open.
Bash History Exists Both in Memory and in a File
The first thing to understand is that Bash history is not managed solely through $HISTFILE.
Each running Bash process independently keeps its own history in memory.
For example, if Bash is running in three terminals, the situation looks like this:
Bash A ── history in memory
Bash B ── history in memory
Bash C ── history in memory
↓
$HISTFILE
Therefore, when directly editing $HISTFILE, you need to consider not only the file itself, but also the history held by each Bash process.
First, Write Out the History from All Sessions and Disable History Recording
First, run the following in every Bash session that is currently open:
history -a
set +o history
history -a appends history entries from that Bash session that have not yet been saved to $HISTFILE.
In other words, by running it in every session, you can collect each session's unsaved history into the file:
Bash A ─┐
Bash B ─┼─ history -a → $HISTFILE
Bash C ─┘
The next command,
set +o history
temporarily disables history recording in that Bash session.
The key point is to run this in every session as well.
Edit the History File from One Session
Once you have run
history -a
set +o history
in every Bash session, edit $HISTFILE from one of them.
For example, with Emacs:
emacsclient -nw "$HISTFILE"
Of course, you can use any editor you like.
vim "$HISTFILE"
or
"${EDITOR:-vi}" "$HISTFILE"
will work as well.
Make the necessary changes, such as deleting unwanted history entries, and save the file.
Reload the History in Every Session After Editing
Simply editing the file does not remove the pre-edit history still held in memory by Bash processes that are already running.
Therefore, run the following again in every Bash session:
history -c
history -r "$HISTFILE"
set -o history
Each command has the following meaning.
history -c
clears the history currently held in memory by that Bash process.
Next,
history -r "$HISTFILE"
loads the edited $HISTFILE.
Finally,
set -o history
re-enables history recording.
This puts the sessions into the following state:
edited $HISTFILE
│
history -r│
┌─────────┼─────────┐
↓ ↓ ↓
Bash A Bash B Bash C
All sessions will now operate using the edited history as their baseline.
Summary of the Procedure
1. Run in every Bash session
history -a
set +o history
2. Edit the history in one Bash session
"${EDITOR:-vi}" "$HISTFILE"
3. Run in every Bash session
history -c
history -r "$HISTFILE"
set -o history
That is the basic procedure.
Why Use history -a Instead of history -w?
At first glance, it may seem safer to run
history -w "$HISTFILE"
before editing.
However, caution is required when multiple Bash sessions exist.
history -w rewrites $HISTFILE using the history currently held in memory by the current Bash process.
For example, suppose you have:
Bash A history: A1 A2 A3
Bash B history: B1 B2 B3
Even if Bash B's history has already been written to $HISTFILE, Bash A may not have loaded it.
If you then run
history -w "$HISTFILE"
from Bash A, the file will be rewritten based on the history known to Bash A, potentially causing history originating from other sessions to be lost.
By contrast,
history -a
appends unsaved history entries.
Therefore, when collecting history from multiple sessions,
history -a
is more appropriate.
Even This Is Not "Perfect"
Following the procedure above makes the operation considerably safer, but strictly speaking, it is not foolproof.
The Bash history file is not a transactional database designed for concurrent updates from multiple Bash processes.
In other words, if a new command is executed in another session while you are running
history -a
in each session, or if writes to the history file overlap, timing-dependent problems can still occur.
Also, commands executed after
set +o history
will not be recorded in that session's normal history.
Therefore, it is best to avoid continuing normal work while editing the history.
The Most Reliable Approach Is to Close the Other Bash Sessions
If reliability is the priority, there is a simpler approach.
Close every Bash session except the one you will use to edit the history.
The fact that multiple processes are accessing the same $HISTFILE is itself the source of potential conflicts, so reducing
Bash A
Bash B
Bash C
to
Bash A
before editing the history substantially reduces the number of issues you need to account for.
In other words:
- Want to keep multiple sessions open → write out the history from every session, disable recording, edit, and reload it in every session.
- Prioritize reliability → close the other Bash sessions before editing.
Conclusion
If you want to edit $HISTFILE while keeping multiple Bash sessions open, the following procedure is practical.
Before editing, in every session:
history -a
set +o history
In one session:
"${EDITOR:-vi}" "$HISTFILE"
After editing, in every session:
history -c
history -r "$HISTFILE"
set -o history
The important point is not to stop after editing $HISTFILE itself.
Each Bash process independently keeps its own history in memory. Therefore, the underlying idea is to collect each session's unsaved history into $HISTFILE before editing, and then synchronize every session with the contents of the edited $HISTFILE afterward.
However, Bash history management does not provide strong mutual exclusion between multiple processes. If you need to edit the history with maximum reliability, the simplest approach is to close the other Bash sessions before doing so.
Bashの履歴ファイルを安全に手動編集する方法
Bash のコマンド履歴は通常 $HISTFILE(多くの環境では ~/.bash_history)に保存されています。
不要な履歴をまとめて削除したい場合など、このファイルを直接エディタで編集したくなることがあります。
ただし、複数の Bash セッションを同時に開いている環境では注意が必要です。単純に $HISTFILE を編集すると、別の Bash セッションが持っている履歴によって、後から編集内容が上書きされる可能性があります。
この記事では、複数の Bash セッションを開いたまま、履歴ファイルをできるだけ安全に編集する手順を整理します。
Bashの履歴には「メモリ」と「ファイル」がある
まず押さえておきたいのは、Bash の履歴が単純に $HISTFILE だけで管理されているわけではないことです。
実行中の各 Bash プロセスは、それぞれ独立して履歴をメモリ上に保持しています。
例えば3つのターミナルで Bash を起動している場合、
Bash A ── メモリ上の履歴
Bash B ── メモリ上の履歴
Bash C ── メモリ上の履歴
↓
$HISTFILE
という状態になります。
そのため $HISTFILE を直接編集する場合は、ファイルだけではなく、各 Bash プロセスが持っている履歴も考慮する必要があります。
まず全セッションの履歴を書き出して記録を停止する
最初に、現在開いているすべての Bash セッションで次を実行します。
history -a
set +o history
history -a は、その Bash セッションでまだ履歴ファイルに保存されていない履歴を $HISTFILE に追記します。
つまり、全セッションで実行することで、
Bash A ─┐
Bash B ─┼─ history -a → $HISTFILE
Bash C ─┘
という形で、それぞれの未保存履歴をファイルに集められます。
続く
set +o history
は、その Bash セッションでの履歴記録を一時的に無効化します。
これも全セッションで実行するのがポイントです。
1つのセッションから履歴ファイルを編集する
すべての Bash セッションで
history -a
set +o history
を実行したら、1つのセッションから $HISTFILE を編集します。
例えば Emacs なら、
emacsclient -nw "$HISTFILE"
もちろんエディタは何でも構いません。
vim "$HISTFILE"
や
"${EDITOR:-vi}" "$HISTFILE"
でも構いません。
ここで不要な履歴を削除するなど、必要な編集を行って保存します。
編集後は全セッションの履歴を再読み込みする
ファイルを編集しただけでは、既に起動している Bash のメモリ上には編集前の履歴が残っています。
そこで、再びすべての Bash セッションで次を実行します。
history -c
history -r "$HISTFILE"
set -o history
それぞれの意味は次のとおりです。
history -c
現在の Bash がメモリ上に保持している履歴をクリアします。
続いて、
history -r "$HISTFILE"
編集済みの $HISTFILE を読み込みます。
最後に、
set -o history
で履歴記録を再び有効化します。
これによって各 Bash セッションは、
編集済み $HISTFILE
│
history -r│
┌─────────┼─────────┐
↓ ↓ ↓
Bash A Bash B Bash C
という状態になり、全セッションが編集済みの履歴を基準に動作するようになります。
手順をまとめると
1. 全 Bash セッションで実行
history -a
set +o history
2. 1つの Bash セッションで履歴を編集
"${EDITOR:-vi}" "$HISTFILE"
3. 全 Bash セッションで実行
history -c
history -r "$HISTFILE"
set -o history
これが基本的な流れです。
なぜ history -w ではなく history -a なのか
一見すると、編集前に
history -w "$HISTFILE"
を実行した方が確実そうに見えます。
しかし、複数の Bash セッションが存在する場合には注意が必要です。
history -w は、現在の Bash がメモリ上に持っている履歴を使って $HISTFILE を書き直します。
例えば、
Bash A の履歴: A1 A2 A3
Bash B の履歴: B1 B2 B3
という状態で、Bash B の履歴が $HISTFILE に反映されていても、Bash A がそれを読み込んでいない可能性があります。
その状態で Bash A から
history -w "$HISTFILE"
すると、Bash A が知っている履歴を基準にファイルが書き直され、他セッション由来の履歴を失う可能性があります。
これに対して、
history -a
は未保存の履歴を追記します。
そのため複数セッションから履歴を集める用途では、
history -a
を使う方が適しています。
それでも「完全」ではない
ここまで行えばかなり安全ですが、厳密には完全な方法ではありません。
Bash の履歴ファイルは、複数の Bash プロセスから同時に更新するためのトランザクショナルなデータベースではありません。
つまり、
history -a
を各セッションで実行している最中に別セッションで新しいコマンドが実行されたり、履歴ファイルへの書き込みが競合したりすれば、タイミング依存の問題が発生する余地があります。
また、
set +o history
を実行した後のコマンドは、そのセッションの通常の履歴には記録されません。
したがって、履歴編集作業中に通常の作業を続けるのは避けた方がよいでしょう。
最も確実なのは他の Bash を終了すること
確実性を優先するなら、もっと単純な方法があります。
履歴を編集する Bash 以外のセッションを終了してしまうことです。
複数プロセスが同じ $HISTFILE を扱っていること自体が競合の原因なので、
Bash A
Bash B
Bash C
を
Bash A
だけにしてから履歴を編集すれば、考慮すべき問題は大幅に減ります。
つまり、
- 複数セッションを維持したい → 全セッションで履歴を書き出し、停止・再読み込みする
- 確実性を優先したい → 他の Bash セッションを終了してから編集する
という使い分けになります。
結論
複数の Bash セッションを開いたまま $HISTFILE を編集するなら、次の手順が実用的です。
編集前に全セッションで
history -a
set +o history
1セッションで
"${EDITOR:-vi}" "$HISTFILE"
編集後に全セッションで
history -c
history -r "$HISTFILE"
set -o history
重要なのは、$HISTFILE だけを編集して終わりにしないことです。
各 Bash プロセスはそれぞれ独立した履歴をメモリ上に保持しています。そのため、編集前には各セッションの未保存履歴を $HISTFILE に集約し、編集後には全セッションを編集済み $HISTFILE の内容に同期する、という考え方になります。
ただし Bash の履歴管理には複数プロセス間の強力な排他制御があるわけではありません。履歴を確実に編集する必要がある場合は、他の Bash セッションを終了してから作業する方法が最もシンプルです。
Top comments (0)