Vimで複数ファイルを横断検索する(vimgrep + cwindow)
プロジェクト内の複数ファイルから特定のキーワードを探したいとき、いちいちファイルを開いてから検索する必要はありません。:vimgrepにワイルドカードでファイルを指定すれば、開いてすらいないファイルもまとめて検索できます。
基本の書式
:vimgrep /{検索パターン}/g {検索対象ファイル} | cwindow
:vim /{検索パターン}/g {検索対象ファイル} | cw
検索対象ファイルにはワイルドカードが使えます。例えば次のように指定できます。
:vim /numpy/g *.py | cw
:vim /autocmd/g **/*.vim | cw
:vim /structure/g ~/src/*.c | cw
**を使うと、カレントディレクトリ配下を再帰的に検索できます。1つ目の例はカレントディレクトリのPythonファイルからnumpyという文字列を、2つ目はカレントディレクトリ配下すべてのvimファイルからautocmdという文字列を検索します。
**を使うとサブディレクトリまで再帰的に検索できます。開いていないファイルも対象にできる点が:bufdoとの違いです。開いているバッファだけを検索したい場合
このコマンドはファイルパスを指定して検索するため、まだ開いていないファイルも対象にできるのが特徴です。逆に、すでに開いている複数バッファだけを対象にしたい場合はbufdo + vimgrepを使う記事を参照してください。使い分けの目安はこうなります。
| 目的 | コマンド |
|---|---|
| 開いている全バッファを検索 | :bufdo vimgrep ... % | cw |
| ファイル・ディレクトリを指定して検索 | :vimgrep ... {file} | cw |
結果一覧を自動表示する
autocmd QuickFixCmdPost *grep* cwindow
設定ファイルに書いておけば、grep系コマンドの実行後に毎回自動でQuickfixウインドウが開くようになります。
大量ファイルを検索するときの注意
vimgrepは各ファイルを実際にVimの編集バッファとして読み込みながら検索するため、ファイル数が多いと外部のgrepコマンドより低速になります。数千ファイル規模のリポジトリ全体を検索したい場合は、OSのgrepを呼び出す外部grepのほうが向いていることもあります。両者の違いはvimgrepとgrepの違いの記事で詳しく比較しています。
設定ファイル一式をディレクトリごと検索したいとき、`**/*.vim`のような再帰ワイルドカードを覚えてから、ファイラーで1つずつ開いて探す作業がほぼなくなりました。数百ファイル規模のプロジェクトでは体感で少し待つこともありますが、日常的な設定ファイルの検索であれば十分な速度で使えています。
まとめ
開いていないファイルまで含めて横断検索したいときは:vimgrep /パターン/g ファイル指定 | cw。**の再帰ワイルドカードと組み合わせれば、プロジェクト全体からのキーワード検索も1コマンドで完結します。