VimのE325 ATTENTIONの読み方 スワップファイルを消す前に見る2行
Vimでファイルを開いた瞬間に画面いっぱいの英文が出て、最後に[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:と聞かれる。これがE325です。検索すると「.swpを消せば直る」という説明が並びますが、消して直るのは画面が出なくなることだけで、消した中身は戻りません。
実際に手元でVimをkill -9して何度か再現したところ、この画面は保存し忘れた変更が残っているときか、別のVimが同じファイルを開いているときにしか出ませんでした。逆に言えば、出た時点で失うものがあります。どちらなのかは画面の2行を見れば分かります。
検証環境:Vim 9.1とNVIM v0.12.4(macOS)。tmuxの中でVimを起動して編集し、kill -9でプロセスを落としてから開き直す、という手順で再現しました。掲載している画面とswapinfo()の値はすべて実行結果です。ユーザー名とホスト名だけ伏せてあります。
目次(8項目)
| 選択肢 | これだけ覚える |
|---|---|
| r | 未保存の変更を取り戻す。まずこれ |
| o | 読み取り専用で開く。別のVimが開いているとき |
| q | 開くのをやめる。判断が付かないとき |
| d | スワップファイルを消す。中身を確認してから |
この画面は「失うものがある」ときにしか出ない
まず誤解を解いておきます。スワップファイルが残っていれば必ずE325が出る、というわけではありません。
保存してからVimをkill -9で落とし、.swpが残っている状態で開き直す実験をしました。結果はE325が出ず、そのまま普通に開きました。残っていたスワップファイルの中身をswapinfo()で見ると、理由が分かります。
:echo swapinfo('.b.txt.swp')
{'pid': 55255, 'dirty': 0, 'version': 'VIM 9.1', ...}
dirtyが0です。スワップファイルの中身とディスク上のファイルが一致していて、取り戻すものが何もない状態を指します。Vimはこれを見て、黙って開き直します。同じ手順で、保存せずに落とした場合はdirtyが1になり、E325が出ました。
つまりこの画面は、警告というより「捨てていいか確認しています」という問い合わせです。反射的にdを押す前に、次の2行を見てください。
見るのは2行だけ
画面には10行以上の説明が並びますが、判断に使うのはprocess IDとmodifiedの2行です。
Found a swap file by the name ".memo.txt.swp"
owned by: user dated: 木 9月 10 18:37:27 2026
file name: /tmp/vimblue-swap-lab/memo.txt
modified: YES
user name: user host name: host.local
process ID: 42499
これはクラッシュしたときの表示です。process IDのうしろに何も付いていません。つまりその番号のプロセスはもう生きていません。modified: YESは、保存されていない変更がスワップファイルに残っていることを表します。取り戻せるものがある状態です。
同じファイルを2つのVimで開くと、表示が変わります。
modified: no
process ID: 50272 (STILL RUNNING)
(STILL RUNNING)が付きました。もう1つのVimが今この瞬間もそのファイルを開いています。ここでeを押して両方から編集すると、あとから保存したほうがもう一方を上書きします。この表示を見たら編集せず、oで読み取り専用にするかqでやめるのが安全です。読み取り専用でファイルを開く方法は別記事にまとめてあります。
| 画面の状態 | 起きていること | 選ぶもの |
|---|---|---|
(STILL RUNNING)が付く | 別のVimが開いている | oまたはq |
付かない・modified: YES | 落ちて未保存の変更が残る | r |
| そもそも画面が出ない | 取り戻すものが無い | 気にしなくてよい |
ひとつ落とし穴があります。(STILL RUNNING)は、そのプロセスが同じマシンで動いているときにしか出ません。ヘルプにも「ネットワーク越しにファイルを編集している場合、プロセスが別のコンピュータで動いているため、このヒントが出ないことがある」と書かれています。共有ストレージやリモートのファイルを扱っているときは、表示が無いことを「誰も開いていない」と読み替えないでください。
(R)ecoverしたあとが本番
rを押すと、スワップファイルの内容がバッファに読み込まれます。ここで多くの人が終わったと思いますが、この時点でディスク上のファイルはまだ古いままです。復旧したのはVimの中だけです。
実際に、保存せずに落とした状態から復旧して確かめました。
# ディスク上のファイル(保存していないので元のまま)
let name = "vim"
let count = 1
# :recover したバッファを別名で書き出したもの
let name = "vim" " 保存前の編集
let count = 1
上書きしていいか自信が無いときは、いきなり:wせずに別名で書き出して見比べます。
:w! memo.txt.recovered
:q
# 差分を見てから、取り込むか決める
diff memo.txt memo.txt.recovered
Vimの中で済ませたいなら:diffsplitでも構いません。vimdiffと:diffsplitの使い方のほうが、行単位で拾い直すときは楽です。
そしてもうひとつ、復旧してもスワップファイルは消えません。手元で確認したところ、:recoverしたあともディレクトリに.memo.txt.swpが残ったままでした。放っておくと次に開いたときも同じ画面が出ます。内容を取り込み終えてから、改めてdを押すか、シェルで消してください。
戻るのは最後に書き出された時点まで
スワップファイルはキーを打つたびに更新されるわけではありません。ここを知らないと「復旧したのに直前の編集が入っていない」と混乱します。
書き出す間隔は2つのオプションが決めています。updatecountは打った文字数、updatetimeは入力が止まってからの時間です。どちらも既定値をそのまま使っている人が多いはずです。
:set updatecount? " updatecount=200
:set updatetime? " updatetime=4000
200文字打つか、手が4秒止まると書き出されます。これを実験で確かめました。編集してから0.8秒でVimを落とした場合、復旧しても編集は入っていませんでした。同じ編集をしてから5.5秒待って落とした場合は、編集がそのまま戻ってきました。
クラッシュから救えるのは、この4秒の内側で消えたぶんを除いた残りです。ほとんどの場合は手が止まる瞬間が何度もあるので実害は出ませんが、一気に打ち込んで落ちたときは末尾が欠けます。updatetimeを短くすれば取りこぼしは減りますが、この値はカーソル停止をきっかけに動くプラグインの反応速度も兼ねているので、無闇に小さくすると別のところが忙しくなります。
.swoや.swnの正体
E325の画面でe(Edit anyway)を選ぶと、拡張子が.swoのファイルが増えます。ディレクトリを見て「知らないファイルが増えた」と戸惑うのはこれです。
# (E)dit anyway を選んだ直後
.memo.txt.swo
.memo.txt.swp
memo.txt
Vimは1つのバッファに1つのスワップファイルを必要とします。.swpは先客が使っているので、次の名前として.swoを作ります。さらに重なれば.swn、.swmと、末尾の文字を戻しながら増えていきます。
.swoのほうは、そのVimを普通に終了すれば消えました。残るのは元の.swpです。ディレクトリに.swoが居座っているなら、eで開いたVimもまた落ちた、ということになります。
Neovimはファイルの隣に置かない
Neovimしか使っていない人が.swpを見たことがないのは、置き場所が違うためです。directoryの既定値を比べると分かります。
| エディタ | directoryの既定値 |
|---|---|
| Vim 9.1 | .,~/tmp,/var/tmp,/tmp |
| Neovim 0.12.4 | ~/.local/state/nvim/swap// |
Vimの先頭は.、つまり編集中のファイルと同じディレクトリです。Neovimは状態ディレクトリの下に集めます。Neovimの設定ファイルの置き場所と同じ考え方で、生成物をリポジトリの中に散らかさない作りになっています。
集めたぶん、ファイル名は元のパスを潰した形になります。
~/.local/state/nvim/swap/%private%tmp%vimblue-swap-lab2%note.lua.swp
区切りが%に置き換わっているだけで、フルパスがそのまま名前になっています。E325の画面もこの長い名前で出るので驚きますが、読み方は同じです。
置き場所を1か所にまとめる
Vimを使っていて.swpがリポジトリに紛れ込むのが嫌なら、Neovimと同じ形にできます。
set directory=~/.vim/swap//
末尾のスラッシュ2つが要点で、ファイル名にフルパスを含めるという指定です。これが無いと、別のディレクトリにある同名のファイル同士でスワップファイルがぶつかります。undofileでundo履歴を永続化するときのundodirとまったく同じ書き方です。ディレクトリは自分で作っておく必要があります。
置き場所を移すのは有効ですが、機能自体を切るのはおすすめしません。
set noswapfile
これでスワップファイルは作られなくなり、E325も出なくなります。同時に、落ちたときに戻す手段も無くなります。SSH越しの作業やバッテリーの怪しいノートPCで効いてくるのはまさにこの機能なので、切るなら失うものを分かったうえで切ってください。編集内容を外に出したくない特定のファイルだけ切りたい、という用途ならautocmdでパスを絞るほうが筋が通ります。
この記事を書くまで、E325はdで消すものだと思っていました。実際そうしてきて困らなかったのは、たいてい(STILL RUNNING)が付いた「同じファイルを2つのVimで開いた」ケースだったからだと、今回並べてみて分かりました。検証でいちばん意外だったのは、保存してから落ちた場合にE325がそもそも出ないことです。「スワップが残る=毎回怒られる」と思い込んでいたので、再現しようとして何度も静かに開いてしまい、しばらく手順を間違えたのだと疑っていました。swapinfo()のdirtyを見て、Vimのほうが自分より丁寧に判定していたと気づいた次第です。
まとめ
E325は、取り戻せるものがあるときにだけ出ます。process IDに(STILL RUNNING)が付いていれば別のVimが開いているので触らない、付いていなければクラッシュなのでrで復旧する。この2択に落とし込めば毎回迷わずに済みます。復旧したあとは別名で書き出して差分を見てから取り込み、最後にスワップファイルを消すところまでが一連の作業です。
なお復旧できるのは最後に書き出された時点までなので、この仕組みを保険と考えるのは正しくても、保存の代わりと考えるのは危険です。手が止まった瞬間に:wする癖のほうが確実に効きます。