Hack #32: Vimが強制終了された後の処理
Posted at 2009/06/26ツイート
問題
Vimは編集中ファイルと同じディレクトリにスワップファイルをまき散らします。
例えばaaa.txtというファイルを編集するとき、.aaa.txt.swpというファイル名のスワップファイルを生成します。
これはVimを終了するか、aaa.txtを編集しているバッファを:qではなく:q!で閉じると削除されます。
意図しないOSの再起動などで、Vimが強制終了されることがあります。その際、Vimで編集しているファイルのスワップファイルが散らかったまま残り続けることになります。 過去に生成したスワップファイルがある状態で、そのファイルを新しく起動したVimで開くと、以下のようなエラーが表示されます。

もしも前回のVimの強制終了時に保存していない編集分があることを確信しているならば、rを打鍵して編集分を救出してバッファに反映させることができます。 しかし、多くの場合は過去の編集分は不要で、ファイルを開くたびにdを打鍵して古いスワップファイルを削除する必要があり、非常に煩雑です。
解決
まず当面の問題を解決します。全てのスワップファイルを削除しましょう。
$ ruby -e "Dir.glob(['**/.sw{p, o}', '**/.*.sw{p, o}']) {|f| File.unlink(f) }"
上記ワンライナーでカレントディレクトリ以下の全てのスワップファイルを削除します。 スワップファイルが残っている可能性のあるディレクトリのうち最上位で行なうとよいでしょう。 この処理は探索範囲の広さに比例して時間がかかります。
次に、今後スワップファイルが散らばらないようにしましょう。以下の設定を~.vimrcに記述します。
set directory-=.
今後~/tmp以下にのみスワップファイルが生成されるようになります。
議論
スワップファイル生成場所の候補は、例えばMac OS Xでユーザ名がujihisaの場合、
規定値は.,/Users/ujihisa/tmp,/var/tmp,/tmpとなっています。コンマで区切られた先頭の指定が優先されます。
:set-=を使って.の要素を削除すると、/Users/ujihisa/tmpが先頭にくることによって、今後そこにスワップファイルが
生成されるようになります。
このことで、システム強制終了時などにスワップファイルをまとめて削除することを容易にします。
なお、先ほど例に出したワンライナー
$ ruby -e "Dir.glob(['**/.sw{p, o}', '**/.*.sw{p, o}']) {|f| File.unlink(f) }"
これはファイル名が与えられたファイルに対するスワップファイルと、無名バッファに対するスワップファイルの
両方を削除します。swpファイルが既に存在するときVimはswo, swn, …とファイルを生成していきます。
ここでは大雑把にswpとswoだけを削除するようにしてみましたが、厳密に行なうならば
もしswpがあれば同じ元ファイルに対するswoがあるか確認して、さらにもしそれが存在すれば…と分岐を行なう必要があります。
ところで、より強気な解決方法として、そもそもスワップファイルを生成しないという設定があります。
set directory=
この設定は自動保存を有効にしている使用者と非常に相性が良いですが、そうでない使用者には必ずしもおすすめできません。 Vim強制終了時の救出を諦めなければならなくなり、日頃の編集作業の緊張感が高まります。
ujihisaもどる
blog comments powered by Disqus