Vimには、どこで使うのかよくわからない機能がたくさん備わっています。
そんな機能の1つに、:windo、:bufdo、:tabdo、:argdo などがあります。これらは複数ファイルの処理にうまく使えば、強力な機能になります。
この記事では、これらの活用パターンについて調べた結果をご紹介します。
パターン1. 複数ファイルの文字列置換
開かれた全てファイルに対して、例えば「文字列 emacs を文字列 vim に全て置換したい」という場合、次のように実行します。
:windo %s/emacs/vim/g (すべてのウインドウが対象) :bufdo %s/emacs/vim/g (すべてのバッファが対象) :tabdo %s/emacs/vim/g (すべてのタブが対象)
Linux の場合だと sedコマンドで行う内容かもしれませんが、vim で開いた状態だと実行結果も確認できて便利ですね。
もちろん、vim をワンライナーとしてシェルから実行する場合にも使えます。ただ、その場合はには、sedなどのコマンドを使った方が性能面では優れていると思いますので、あまりやり過ぎは注意です。
ちなみに、未保存のバッファがあった部コマンドを実行するりすると、うまく保存ができなかったりするらしいです。そのため、下記のように保存しながら実行すると良いようです。
:bufdo %s/emacs/vim/g | w (変更有無に関係なく全バッファを保存する) :bufdo %s/emacs/vim/g | update (変更したバッファだけ保存する) :bufdo! %s/emacs/vim/g (保存せずに、強制的に全バッファで置換を実行する)
パターン2. 行番号を表示したい
開かれた全てファイルに対して、行番号を表示したい場合、次のように実行します。
:windo :set number (すべてのウインドウが対象) :bufdo :set number (すべてのバッファが対象) :tabdo :set number (すべてのタブが対象)
通常は、設定ファイルで set number を組み込んでいれば不要です。しかし、一時的に作ったサーバーなど、常用しない環境で Vim / neovim を使うときには重宝します。
ちなみに、現在行からの相対位置の行番号を表示させたい場合は、下記を実行しましょう。
:windo :set relativenumber (すべてのウインドウが対象) :bufdo :set relativenumber (すべてのバッファが対象) :tabdo :set relativenumber (すべてのタブが対象)
パターン3. 比較する
vimgrep などもありますが、開いているファイルたちをすぐに比較するには便利です。
:windo diffthis (すべてのウインドウが対象) :bufdo diffthis (すべてのバッファが対象)
上記のコマンドで比較を開始して、次のコマンドで比較を終了します。
:windo diffoff (すべてのウインドウが対象) :bufdo diffoff (すべてのバッファが対象)
こちらは機能の性質から、ウインドウやバッファに使うことはあっても、タブに使うことはないはずです。
パターン4. 特定の文字をハイライトする(検索する)
次のようにハイライト設定を実行します。あらかじめ設定してあるなら不要です。
:set hlsearch
そして、次のように例えば文字列 vim を検索してみます。
:windo /vim (すべてのウインドウが対象) :bufdo /vim (すべてのバッファが対象) :tabdo /vim (すべてのタブが対象)
そうすると、すべてのウインドウで検索できた文字列がいずれもハイライトされます。
各ファイルでキーワードを探す手間が省けて便利ですし、:vimgrep などとも少し違う使い方ができます。
パターン5. マクロを実行する
記録したマクロを実行することも可能です。例えば、レジスタx に記録したマクロを実行する場合は、次のようにコマンドを実行します。
:windo execute "normal! @x" (すべてのウインドウが対象) :bufdo execute "normal! @x" (すべてのバッファが対象) :tabdo execute "normal! @x" (すべてのタブが対象)
あるいは execute を省略すると、
:windo normal! @x (すべてのウインドウが対象) :bufdo normal! @x (すべてのバッファが対象) :tabdo normal! @x (すべてのタブが対象)
この時に実行するマクロが内容を変更するものであれば、次のいずれかの方法で実行した方が良いかもしれません。(:windoの場合)
:windo execute "normal! @x" | w (変更有無に関係なく全バッファを保存する) :windo execute "normal! @x" | update (変更したバッファだけ保存する) :windo! execute "normal! @x" (保存せずに、強制的に全バッファでマクロを実行する)
パターン6. ファイル名の一覧を表示する
表示しているウインドウのファイル名を一覧表示します。
:windo echo bufname("%")
タブやバッファの場合は、あまりやるい意味がないのでウインドウのみに使える小技です。
パターン7. 特定の行だけ置換する
置換と検索を組み合わせた応用技も利用できます。例えば、editor という文字列がある行の文字列 emacs を文字列 vim に一括置換する場合は、次のように実行します。
:windo g/editor/s/emacs/vim/g (すべてのウインドウが対象) :bufdo g/editor/s/emacs/vim/g (すべてのバッファが対象) :tabdo g/editor/s/emacs/vim/g (すべてのタブが対象)
複雑に見えますが、結局は検索と置換、windo/bufdo/tabdo の組み合わせでしかないので、覚えるのは難しくないはずです。
パターン8. 外部コマンドを実行する
外部コマンドを実行することも可能です。例えば、一番使えるであろう行数のカウントは次のように実行します。(Linuxの場合)
:windo !wc -l % (すべてのウインドウが対象) :bufdo !wc -l % (すべてのバッファが対象) :tabdo !wc -l % (すべてのタブが対象)
パターン9. スクロールを同期させる
分割したウインドウを見比べるために、スクロールを同期させることができます。(タブ/バッファでは、使いどころが考えにくいために省略)
:windo set scrollbind (すべてのウインドウが対象) :windo se scb (上記の省略形)
まだ、スクロールの同期をすべて解除させることも可能です。
:windo set noscrollbind (すべてのウインドウが対象) :windo se noscb (上記の省略形)
Vim の diff機能を使う場合などには、うまく使える機能です。
パターン10. 再読み込み
開いているファイルをすべて再読み込みすることも可能です。
:windo e! (すべてのウインドウが対象) :bufdo e! (すべてのバッファが対象) :tabdo e! (すべてのタブが対象)
こちらで指定した e は edit コマンドの省略ですから、edit / edit! / e / e! のいずれでも実行可能です。また、!を指定すると、保存されないまま再読み込みされてしまうので、注意してください。
このパターンは、次の記事でも紹介しています。
この他にもパターンがあるかもしれませんので、ぜひ windo / bufdo / tabdo に慣れておきましょう。
Vimの活用パターンを学ぶには
先にも述べたように、「何に使うの?」という機能がたくさん備わっています。それらを学ぶには、次のような書籍で学ぶことをお薦めします。
Vim/neovim関連の書籍で、もっとも評判が良くてバイブルと呼んでる人もいる一冊です。Vim/neovimのバージョンに依存しない沢山のTips形式で、その表題通りに「思考のスピードで編集」できるようになるノウハウが詰まっています。その高い評価は Amazon のレビューからも分かる通りです。Vimmer なら必ず一度は読んでおいて間違いありません。
こちらもVim関連の書籍で評価が高い書籍の一冊です。vim-jpで見かける上級Vimmer(Vimサポーターズ)の皆様による、Vimを実践で使ったノウハウからプラグイン関連の情報が詰まっています。日本の Vim界隈を知る上でも是非一読しておきたい一冊です。
Vim/neovim の設定ファイルやプラグインなど、Vim script に関するノウハウがいくつも詰まった一冊です。日本で Vim Script をここまで深く解説している唯一の書籍と言えます。Vim力を伸ばしたいと考えるなら、絶対に避けては通れない書籍でしょう。