ripgrepでファイルを高速検索する

vimのctrlp.vimというファイル検索プラグインでホームディレクトリ以下のファイルを検索することがよくあるのですが、この検索がなかなか遅いもので。

なにか良いファイル検索コマンドはないかと探していたところ、驚くべき速度のコマンドripgrepという物を発見しました。
今まで検索コマンドは、The Sliver Searcher(agコマンド)を用いていたのですが、それを遥かに凌駕する優れものですので、皆さんも使用してみてはいかがでしょうか。

find vs The Sliver Searcher vs ripgrep

さて、まずそれぞれのコマンドの速度を比較してみます。

  • findコマンド(unix系OSでお馴染みの検索コマンド)
  • agコマンド(The Silver Searcher 速いと噂)
  • rgコマンド(今回おすすめしているコマンド)

私がvimプラグインのctrlp.vimで、よく拡張子での絞り込みを行うので、「ホームディレクトリ以下のcppファイルを正規表現にて検索」という条件で速度比較を行いたいと思います。

$ find -E ~/ -type f -regex ".+\.cpp"
$ ag -g ".+=.cpp" ~/
$ rg --files ~/ | rg ".+\.cpp"

※ rgコマンドにて--filesオプションを使用すると、検索対象のファイルのリストを表示するのみとなり、正規表現での絞り込みができない。ので、パイプで繋げて「全ファイルリストアップ→正規表現での絞り込み」という手順を踏んでいる。

実行速度の比較

timeコマンドにて実行速度を比較します。
私はMac(zsh)なので、/usr/bin/timeを叩くことになります。(timeコマンドは、zshが提供するtimeコマンドを実行します。/uer/bin/timeとは別物です。注意しましょう。)

$ /usr/bin/time find -E ~/ -type f -regex ".+\.cpp$"
        1.77 real         0.29 user         0.92 sys
$ /usr/bin/time ag -g ".+=.cpp$" ~/
        4.07 real         2.91 user         0.64 sys
$ /usr/bin/time rg --files ~/ | rg ".+\.cpp$"
        0.23 real         0.58 user         1.73 sys
  • find : 1.77s
  • ag (The Sliver Searcher) : 4.07s
  • rg (ripgrep) : 0.23s

私の環境では以上のような結果となりました。rgがagよりも約17倍速いという結果に。
少し意外だったこととして、agよりもfindコマンドの方が速かったという点です。

ripgrepのインストール

Macの方はHomebrewから

$ brew install ripgrep

Ubuntuの方は18.10以降のOSの場合は公式のパッケージに上がっているので、apt-getにて。

$ sudo apt-get install ripgrep

その他OSの場合は、ripgrepの公式githubのREADMEに各OSでのインストールがまとめてあるので、そちらを参考にしましょう。

https://github.com/BurntSushi/ripgrep

vimのファイル検索ctrlp.vimからrgコマンドを叩く

私としては、ここからが本題。
rgコマンドを用いてvim内でファイル検索を高速化しましょう!

私の用いているファイル検索プラグインctrlp.vimでの設定方法を備忘録も兼ねて記述していきます。

let g:my_regexp = "'.+\\.(cpp|hpp|c|h)

g:ctrlp_user_commandという変数にしようしたいコマンドをセットすることで、ctrlp.vimでファイル検索を行う際のコマンドを指定できます。

rgコマンドやagコマンドがインストールされていない場合を考えて、デフォルトではfindコマンドを仕様し、if executable('rg')節内にrgコマンドが使用可能だった場合の設定を記述しています。

※ VimScriptでのダブルクォート内に特殊文字を入力する際はエスケープが必要となることがあります。(バッククォートはダブルバッククォートとします。)
※ findコマンドで2>/dev/nullとしているのは、閲覧権限のないファイルを探した際に表示されるエラーメッセージfind /Users/XXX/Library/Messages: Operation not permittedを捨てるためのもの。agでは--silent、rgでは--no-messagesに該当します。
※ ag、rgコマンドでは、カラーターミナル用のカラーコードがデフォルトで出力されるため--nocolor--color neverというオプションをつけてカラーコードの出力をしない設定にしています。
※ コマンド内の%sは、ctrlp.vimで後ほど展開される文字列ですの検索対象ディレクトリの文字列が実行時に展開されます。

私はctrlp.vimの設定で、常にキャッシュを使用して検索していたのですが、rgコマンドがここまで速いと毎回検索しても良いのではと思えてきました。

ripgrepの使い方

ここまではファイル検索として使用してきましたが、もちろんファイル内の文字列検索としてもしようできます。

例えば、カレントディレクトリ以下で “hoge” という文字列を含むファイルを検索する場合、

$ rg hoge ./

となります。
ここでの詳しい説明は省きますので、各自helpを参照してみましょう。

$ rg --help

以上、ripgrepを用いてファイルを高速検索する方法についてでした。