Rust製ツールを使って定時で帰ろう (ripgrep,fd,exa)

June 19, 2018

各種linuxコマンドをリッチで処理速度も早いRust製のCLIに置き換ると幸せになれるかもという話。タイトルが煽り気味で恐縮ですが、作業効率はわりかし上がると思うのでおすすめです。

(2023/09/25追記)

exaがarchiveされezaにportされたようなので更新しました。

(追記終わり)


今回紹介するのは以下の3つのCLIです。

  • ripgrep
  • fd
  • exa eza

ripgrep

https://github.com/BurntSushi/ripgrep

コマンド名はrggrepの拡張版。agより若干速い。

  • brewで入ります。 brew install ripgrep
  • -z で圧縮ファイルの中身も検索
  • .gitignore に記載のディレクトリ・ファイルを無視してくれる、すべて含むことも可能
  • SJISやEUC-JPなどもサポート、 -E で任意のエンコーディング指定が可能
  • -t でファイルタイプ指定のinclude、 -T でファイルタイプ指定のexclude。-tpyでPython, -TjsでJSを除外、といった風に。
  • -g ファイルリストに対してglobできる。-g '!*.min.js'といった感じに!を入れるとexcludeに反転する。
  • -r で置換。まず検索して検索結果の末尾に-rを追加する流れ。
    • 構文例: rg 'fast\s+(\w+)' README.md -r 'fast-$1'
    • ただしripgrepは方針としてoverwriteはサポートしないので注意。置換結果の表示のみ。

globとファイルの中身への検索を組み合わせてrg foo -g '*.min.js' ./publicとか書けるのがいい。 部分一致でなくパターンマッチングも使えます、rg -e '^foo' -g '*.md' こんな感じ。 巨大なリポジトリで探しものをしているときとかに重宝します。

fd

https://github.com/sharkdp/fd

コマンド名はfdfindの拡張版。

  • brewで入ります。 brew install fd
  • オプション無しでregexパターンを渡します。cd /etc && fd '^x.*rc$'
  • 末尾でのディレクトリ指定が直感的でいい。 fd '^x.*rc$' /etc
  • -e 拡張子指定。あんま使わないかも、fd 'png$'みたいにパターンマッチを書くことのほうが多い。
  • -d maxDepthのこと。あんま使わないかな。
  • -E excludeパターンマッチを書ける。-iよりこっちのほうがよく使うかも。node_modulesの除外などに。
  • -0 検索結果をNULLでセパレートしてくれる、検索結果をリダイレクトしてxargsへ渡したいときに助かります。

総じて、findを使い慣れていればあまり困らないものではありますが、findより直感的に書け、また処理速度がかなり速いので作業効率は上がりやすいです。

exa

https://github.com/ogham/exa https://github.com/eza-community/eza

コマンド名はezalsの拡張版でツリー表示の機能も内包されている。

  • brewで入ります。 brew install eza
  • -l 通常のlsっぽい表示になる。デフォルトはgrid表示なのだけど、個人的にちょっと見づらいのでこっちを好んで使います。
  • -T lsを再帰的に行いかつツリー表示してくれる、これが便利
  • -I ignoreパターンを書ける、ツリー表示時に-I "node_modulesなどと指定します
  • -L いわゆるmaxDepth、intで指定。思いがけず階層が深かったときに。

カラフルで見やすい。eza -lha, eza -Tlあたりをsnippetやaliasに入れておくといいです。私はalias l="eza -lha"をzshに入れてます。

おまけ:Vimとripgrepの連携

vimgrepをrgに置き換えるのもおすすめです。--sort-filesを付けると速度は少し落ちますが、sort済み結果を返してくれます、Qfreplaceとの組み合わせでよく使います。

if executable("rg")
    set grepprg=rg\ --vimgrep\ --no-heading
    set grepformat=%f:%l:%c:%m,%f:%l:%m
endif
command! -nargs=* -complete=file Rg :tabnew | :silent grep --sort-files <args>
command! -nargs=* -complete=file Rgg :tabnew | :silent grep <args>

fzf連携も便利です。

command! -bang -nargs=* Ripgrep
  \ call fzf#vim#grep(
  \   'rg --column --line-number --no-heading --color=always '.shellescape(<q-args>), 1,
  \   <bang>0 ? fzf#vim#with_preview('up:60%')
  \           : fzf#vim#with_preview({'options': '--exact --reverse --delimiter : --nth 3..'}, 'right:50%:hidden', '?'),
  \   <bang>0)

所感

WindowsなどでSJISも対象にしたい場合には無理にrgを使わず、ptを使うのもおすすめです。Go製なのでバイナリを置くだけですぐ使えますし、速度もag並です。

よく使うツールの手入れといいますか、速くできるところは極力高速化していきたいものです。まぁ、zshrcやvimrcの手入れなんかも含めるとキリがないのですが…。特にripgrepとfdは処理速度の速さが売りなので、よければ入れてみてください。

参考



Recent blog posts



(c) Copyright 2023 Kotaro Yoshimatsu