fzf とは
fzf はインタラクティブな曖昧検索 (Fuzzy Search) ができる、UNIX 思想のフィルターツールです。フィルターとして機能する特徴から、パイプで繋ぐことにより他の UNIX ツールと容易に連携できます。以下の例では find コマンドの結果を受け取り、選択したファイルを標準出力に出力しています。
環境構築
以下の環境を使用しました。
MacOS: 14.1 (23B74)
zsh: zsh 5.9 (x86_64-apple-darwin23.0)
まずは fzf と fd をインストールします。ここで fd という別のツールが出てきますが、ファイル探索の候補から node_module などの不要フォルダーを除外する1ために使用します。
brew install fzf
brew install fd
# ファイル検索に fd を使い、任意のフォルダーを検索対象から外す。
export FZF_DEFAULT_COMMAND='fd --hidden --exclude .git --exclude node_modules --exclude .next'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
fzf
とタイプするか <Ctrl+t>
でファイル検索ができるようになりました。
エクスプローラーの操作を置き換える
長いこと VSCode のエクスプローラーを使う中でいくつかの不満2を抱えていました。以下で挙げる、よく使う操作を Z Shell の関数で置き換えていきます。
- ファイルを開く
- ファイルの作成
- フォルダーの作成
- ファイル・フォルダーの削除
- ファイル・フォルダーのリネーム
- ファイル・フォルダーの移動
記事内では 2 つの関数に絞って紹介します。ちなみに "ファイル・フォルダーの移動" はモジュールの import に影響するため、今後もエクスプローラを使います。早速 "ファイル・フォルダーの削除" から見ていきましょう。
# ファイル・フォルダーの削除
frm() {
# fzf -m で複数ファイルを選択できる様にする。選択されたファイルは rm コマンドに渡す。
fzf -m | xargs rm -rf
}
続いて扱う "ファイルを開く" と "ファイルの作成" は少し考慮することが多いです。利便性のため、引数に応じて振る舞いを変えることにしました。
# ファイルを開く / ファイル・フォルダーの作成
fcode() {
# 引数を受け取った場合
if [[ "$#" -ne 0 ]]; then
dir="$(fd -t d | fzf)"
# index.{tsx,test.tsx,css} の様に brace expression で使うことを想定して、複数ファイルを扱えるようにする。
for file_name in "$@"; do
full_path="${dir}${file_name}"
# ファイルが既に存在すれば、そのファイルを開く
if [[ ! -e "$full_path" ]]; then
code "$full_path"
fi
# ファイルが存在しなければ、新規作成する
touch "$full_path" && code "$full_path"
done
# 引数を受け取らなかった場合
else
target="$(fzf)"
# フォルダーが選択された場合、配下のファイルをすべて開く
if [[ -d "$target" ]]; then
code -a $target/**/*
# ファイルが選択された場合、そのファイルを開く
elif [[ -f "$target" ]]; then
code "$target"
fi
fi
}
なかなか使いやすいです!
最終的にいくつかの関数を追加する形で落ち着きました。現時点の .zshrc は Gist に公開しています。
.zshrcGitHub Gist: instantly share code, notes, and snippets.gist.github.com
おわりに
fzf は Go で書かれているらしく、驚くほど高速です。パイプとして機能する特徴から、今回のような用途だけでなく幅広く活躍できるツールだと思いました。
Footnotes
-
検索が使いにくい。階層が深くなると視認性が悪くなる。 ↩