fd 入門 - find より直感的なファイル検索ツール

fd 入門 - find より直感的なファイル検索ツール

この記事で解決できること

  • find の複雑な構文から解放され、fd PATTERN だけで再帰検索できるようになる
  • Ubuntu/Debian 特有の fdfind 問題(コマンド名が fd でない)を解決できる
  • 拡張子・型・gitignore 連携・-x 実行など 実務で使う型 が身につく

結論(使い分けの型)

  • 日常の「あのファイルどこ?」fd PATTERN(速い・短い・色付き)
  • .gitignore を無視して全部探すfd -H -I PATTERN
  • find が必要なケース → 複雑な -newer 条件、-printf 整形、POSIX 限定環境

前提(対象環境)

  • OS: Ubuntu 22.04 / 24.04(Debian 系)を主対象。他ディストリは適宜読み替え
  • fd 8.x 以降を想定

fd とは何か?

結論: fd は Rust 製のモダンなファイル検索ツール。find の代替として、短い構文・高速・gitignore 自動尊重・カラー出力を最初から備える。

fdsharkdp/fd が開発する、find の使いやすい代替コマンド。find の全機能を置き換えるものではないが、日常的なファイル検索の 9 割 は fd の方が速く・短く書ける。

find との主な違い:

観点 find fd
基本構文 find . -name '*.txt' fd '\.txt$' / fd -e txt
マッチ方式 デフォルトは完全一致(-name 部分一致の正規表現
大文字小文字 区別する スマートケース(小文字なら無視)
隠しファイル 検索する デフォルトで除外(-H で含める)
.gitignore 無視しない 自動で尊重(-I で無効化)
出力 単色 カラー(型ごとに色分け)
速度 標準 並列処理で高速

fd をインストールするには?

結論: Ubuntu/Debian では apt install fd-find でインストールするが、コマンド名は fd ではなく fdfind になる。シンボリックリンクか alias で fd に揃えるのが定番。

ディストリごとのインストール:

# Ubuntu / Debian
sudo apt install fd-find

# Fedora / RHEL 系
sudo dnf install fd-find

# Arch Linux
sudo pacman -S fd

# macOS (Homebrew)
brew install fd

# Rust の cargo から
cargo install fd-find

Ubuntu/Debian の罠: コマンド名が fdfind

Debian には別パッケージ(fdclone)との名前衝突があるため、バイナリ名が fd ではなく fdfind になっている。そのまま fd と打つと command not found になる。

fd という名前で使いたい場合は、~/.local/bin にシンボリックリンクを張る:

mkdir -p ~/.local/bin
ln -s "$(which fdfind)" ~/.local/bin/fd

~/.local/binPATH に含まれていない場合は、~/.bashrc に以下を追記して再読み込みする:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

インストールとバージョンの確認:

fd --version
fd 9.0.0

fd の基本的な使い方は?

結論: fd PATTERN でカレントディレクトリ以下を再帰検索する。パターンは部分一致の正規表現で、検索対象のパスは第 2 引数で指定できる。

最小の使い方は、探したい名前の一部を渡すだけ:

fd readme
README.md
docs/readme-ja.md
src/readme.txt

find だと find . -iname '*readme*' と書くところが、fd readme で済む。大文字小文字はスマートケース(パターンが全部小文字なら区別しない)。

検索を始めるディレクトリは第 2 引数で指定する:

# src/ 以下から config を探す
fd config src/

パターンは正規表現として解釈される。ドットやアンカーをそのまま使える:

# .log で終わるファイル
fd '\.log$'

引数を 1 つも渡さない fd は、カレント以下の全ファイル・ディレクトリを一覧する(.gitignore と隠しファイルは除外)。ls -R の代わりに使える。

拡張子・型で絞り込むには?

結論: 拡張子は -e EXT、種類は -t TYPE(f=ファイル / d=ディレクトリ / l=シンボリックリンク / x=実行可能)で絞り込む。複数指定は OR 条件になる。

拡張子での絞り込みは -e--extension)。ドットは不要:

# .jpg と .png を探す(複数指定は OR)
fd -e jpg -e png

種類での絞り込みは -t--type):

# ディレクトリだけを探す
fd -t d node_modules

# 実行可能ファイルだけ
fd -t x

# 空のファイル / ディレクトリ
fd -t empty

主な型の値:

  • f … 通常ファイル
  • d … ディレクトリ
  • l … シンボリックリンク
  • x … 実行可能ファイル
  • e … 空(empty)

パターンと組み合わせれば「src 以下の .rs ファイル」のような検索も一発:

fd -e rs main src/

隠しファイルや .gitignore 対象も検索するには?

結論: fd はデフォルトで隠しファイルと .gitignore 記載のファイルを除外する。-H で隠しファイルを含め、-I で無視設定を無効化、-u(unrestricted)で両方を一度に解除できる。

fd の「気が利く」挙動が、状況によっては邪魔になる。.envnode_modules/ を探したいのに出てこないのはこのため。

# 隠しファイル(ドット始まり)も含める
fd -H '\.env'

# .gitignore / .ignore を無視してすべて検索
fd -I node_modules

# 上記2つを同時に解除(unrestricted)
fd -u secret

-u--no-ignore --hidden の短縮(-HI と等価)。

逆に、特定のディレクトリを明示的に除外したいときは -E--exclude):

# .git とビルド成果物を除外
fd -E .git -E dist -e js

見つけたファイルにコマンドを実行するには?

結論: -x--exec)は結果 1 件ごとにコマンドを並列実行、-X--exec-batch)は全結果をまとめて 1 回だけ実行する。find -exec より速く構文も短い。

find ... -exec の置き換えが -x / -X。プレースホルダで結果を埋め込める。

# .tmp ファイルを1件ずつ削除(並列実行)
fd -e tmp -x rm

# すべての .png をまとめて optipng に渡す(1プロセス)
fd -e png -X optipng

プレースホルダ(-x 内で使える):

  • {} … マッチしたパス全体
  • {/} … ファイル名のみ(basename)
  • {//} … 親ディレクトリ
  • {.} … 拡張子を除いたパス
  • {/.} … 拡張子を除いたファイル名

実例: 全 .jpg を同名の .png に変換する:

fd -e jpg -x convert {} {.}.png

-x rm のような破壊的操作は、まず実行コマンドを付けずに fd -e tmp対象一覧を目視確認 してから流すこと。fd は .gitignore を尊重する分、想定外のファイルが漏れる/含まれる可能性がある。

find と fd の使い分けは?

結論: 日常検索は fd、複雑な条件・整形出力・POSIX 限定環境は find。両者は排他ではなく、速さと手軽さで fd を主、特殊条件で find を従とするのが実務の型。

fd で十分なケース:

# 直近10分以内に変更されたファイル
fd --changed-within 10min

# 1MB を超えるファイル
fd -S +1M

# glob で書きたいとき
fd -g '*.config.js'

find を選ぶべきケース:

  • -printf で出力を細かく整形したい
  • -newer fileA ! -newer fileB のような複合的な時刻比較
  • fd を入れられない / 入れたくない本番サーバ(fd は標準では入っていない)

コピペ用: よく使う型

fd PATTERN              # 名前で再帰検索
fd -e log               # 拡張子で絞る
fd -t d PATTERN         # ディレクトリのみ
fd -H -I PATTERN        # 隠し/除外も含めて全検索
fd -e tmp -x rm         # 結果ごとに実行
fd --changed-within 1d  # 直近1日の変更

次に読む