Vimで複数ファイルを一括処理する方法 windo/bufdo/tabdoの使い分け
開いているファイルすべてに同じ変更を加えたいとき、1枚ずつ手作業でやっていては時間がかかります。:windo・:bufdo・:tabdoを使えば、開いている範囲に対してまとめてコマンドを実行できます。存在は知っていても使いどころが分からない、という人向けにパターンをまとめます。
3つの違いは対象範囲だけ
3つとも構文はまったく同じで、対象になる範囲だけが違います。
| コマンド | 対象 |
|---|---|
:windo | 現在のタブ内の全ウィンドウ |
:bufdo | 開いている全バッファ |
:tabdo | 全タブ |
用語の関係はバッファ・ウィンドウ・タブの違いで整理しているので、そちらも参照してください。
よく使うパターン
一括置換と保存
複数ファイルの一括置換が最も使用頻度が高くなります。:bufdoに続けて通常の:sコマンドを書くだけで、開いている全バッファに同時に効きます。下は分割編集していたうちの1ファイルぶんの見え方です。
I use emacs on weekdays. emacs has good extensibility.
:bufdo %s/emacs/vim/gI use vim on weekdays. vim has good extensibility.
未保存のバッファがあると置換結果がうまく反映されないことがあるため、保存まで含めて実行したほうが安全です。updateは変更があったバッファだけを保存し、wにすると変更の有無に関わらず全バッファを保存します。
:bufdo %s/emacs/vim/g | update
表示・比較に使う
行番号の一時表示や、開いている複数ファイルの比較にも使えます。
:windo set number
:windo diffthis
diffthisは分割したウィンドウ同士を比較するための機能なので、意味合い上ウィンドウかバッファに対して使うのが自然で、タブに対して使うことはまずありません。
マクロを全体に適用する
記録したマクロを開いているファイル全部に適用したい場合も同じ書き方で構いません。
:bufdo normal! @x
マクロが内容を書き換える場合は、置換のときと同様に保存まで含めておくと安心です。
:bufdo normal! @x | update
外部コマンドを実行する
シェルコマンドを各ファイルに対して実行することもできます。行数をまとめて数えたいときなどに使います。
:bufdo !wc -l %
強制実行したいとき
未保存の変更があると処理が止まってしまう場合、コマンドの直後に!を付けると保存を無視して強制的に実行できます。ただし変更内容は破棄されるので、意図しないデータ消失に注意してください。
:bufdo! %s/emacs/vim/g
{windo|bufdo|tabdo} {コマンド}で共通なので、覚えるのは対象範囲の違いだけです。書き換え系のコマンドを流すときは| updateを付けて保存まで一気に済ませると安全です。
設定ファイルを分割したリポジトリで、複数ファイルにまたがるリネームを:bufdoで一気に片付けたことがあります。sedでも同じことはできますが、Vimで開いた状態のまま実行結果をその場で確認できるのが地味に便利で、以来ちょっとした一括置換はVim側で済ませることが増えました。
まとめ
windo/bufdo/tabdoは対象範囲が違うだけで使い方は共通なので、1つ覚えれば残り2つもすぐ使えます。置換・行番号表示・比較・マクロ適用・外部コマンド実行など、応用範囲の広さが魅力です。