【Linux】findコマンドの使い方完全ガイド|ファイル名・階層・日時検索から一括処理まで

コマンドリファレンス

こんにちは、Bash玄(ばっしゅげん)です。

Linuxサーバーの運用保守や開発環境で作業しているとき、次のような状況に直面した経験はありませんか?

  • 「修正すべき設定ファイルが /etc 配下のどこにあるかわからない」
  • 「ディスク容量が急迫しているが、どのログファイルが肥大化しているのか特定できない」
  • 「30日以上前の古いバックアップファイルを一括で抽出して安全に削除したい」
  • 「大量のシェルスクリプトに実行権限(chmod +x)を一発でまとめて付与したい」

これらを手作業でディレクトリを1つずつ cd しながら探すのは膨大な時間の無駄であり、インフラエンジニアとしては 「手作業は負け」 です。Linux環境において、ファイル探索とバッチ処理の要となるのが find コマンド です。

find コマンドは単なるファイル名検索にとどまりません。階層の深さ(-maxdepth)、ファイル種別(-type)、更新日時(-mtime)、ファイルサイズ(-size)を柔軟に組み合わせ、抽出したファイルに対して -exec や xargs で一括処理を実行できます。本記事では、初学者が迷いやすい基本書式から、現場でそのままコピペして動く実務パターン、安全な一括削除やトラブルシューティングまでを体系的に完全解説します。

【結論】最もよく使うfind検索例5選

まずは「今すぐ目的のファイルを検索したい」「実務で頻出する基本形をコピペしたい」という方のために、現場で毎日のように使われる鉄板の find 実行例を5つ厳選してまとめました。

# 1. カレントディレクトリ配下から特定の拡張子(.log)を再帰的に検索
find . -name "*.log"

# 2. 直下階層のみを検索(サブディレクトリ内を探索しない)
find . -maxdepth 1 -name "*.sh"

# 3. ディレクトリのみを抽出して探す
find . -type d -name "config*"

# 4. 7日以上前に更新された古い通常ファイルを抽出(ログ退避・調査)
find /var/log -type f -mtime +7

# 5. /tmp 配下の3日以上前の古い一時ファイルを安全に一括削除
find /tmp -type f -name "*.tmp" -mtime +3 -delete

これらのコマンドを使いこなすために、まずは基本書式と主要オプションの全体像を整理していきましょう。

findコマンドの基本構文と主要オプション早見表

find コマンドは、Linuxのコマンド体系の中でも非常に論理的で強力な構造を持っています。引数の順序や役割を理解しておくと、複雑な条件指定もスムーズに組み立てられるようになります。

基本書式: find [検索パス] [検索条件] [アクション]

find コマンドの基本書式は、以下の 3つのブロック で構成されます。

find [検索パス] [検索条件] [アクション]
  • [検索パス] : 検索を開始するディレクトリのパスを指定します。カレントディレクトリなら .、システム全体なら /、ログ配下なら /var/log を指定します。パスを省略した場合はカレントディレクトリ(.)が自動で適用されます。
  • [検索条件] : ファイル名(-name)、形式(-type)、更新日時(-mtime)、サイズ(-size)などの評価式(テスト)を指定します。複数並べると自動的に AND条件 として評価されます。
  • [アクション] : 条件に一致したファイルに対して行う処理を指定します。省略した場合は -print(標準出力にパスを1行ずつ表示)がデフォルトで実行されます。一括処理を行う場合は -exec や -delete を指定します。

最低限覚えるべき主要オプション一覧(Markdownテーブル)

日常業務で頻出する主要オプションを機能別に整理しました。困ったときはこの一覧を逆引きリファレンスとしてご活用ください。

分類オプション引数の例機能概要と実務での活用シーン
ファイル名 -name"*.conf"指定パターンに一致するファイルを検索(大文字小文字を厳密に区別)。必ずクォートで囲む。
ファイル名 -iname"*.png"大文字小文字を区別せずに検索(.PNG や .Png も同時ヒット)。
形式絞り込み -typef / d / lファイルの種類を限定(f: 通常ファイル、d: ディレクトリ、l: シンボリックリンク)。
階層制限 -maxdepth1 / 2検索を開始するディレクトリからの最大探索階層を指定(無駄な深掘りを防止)。
階層制限 -mindepth2指定階層より深い場所のみを検索(基点直下のファイルを除外)。
更新日時 -mtime+30 / -7ファイルの最終データ更新日時(日数)で検索(+N: N日超前、-N: N日以内)。
更新日時 -mmin-60 / +120ファイルの最終データ更新日時(分単位)で検索(直近の障害調査・変更特定に最適)。
比較基準 -newerref.txt指定した基準ファイルよりも後に更新されたファイルを抽出。
サイズ -size+100M / -10kファイル容量で検索(k: KB、M: MB、G: GB)。ディスク枯渇調査で必須。
権限 -perm755 / 644指定したパーミッションを持つファイルを検索。
一括実行 -execcommand {} +ヒットした全ファイルに対して指定コマンドを実行({} + でまとめて引数渡し)。
一括削除 -deleteなしヒットしたファイルをその場で直接削除(安全のため末尾に配置する)。
区切り指定 -print0なし結果をヌル文字(\0)区切りで出力(空白を含むファイル名対策で xargs -0 と併用)。

条件別ファイル検索の実務パターン

ここからは、現場のインフラ運用や日々の開発で即戦力となる検索パターンを具体例とともに見ていきましょう。すべてそのままコピー&ペーストして実行可能です。

ファイル名・拡張子で探す(-name / -iname 大文字小文字無視)

最も基本的な検索方法です。ワイルドカード(* や ?)を組み合わせることで、特定の拡張子やプレフィックスを持つファイルを効率よく抽出できます。

# カレントディレクトリ配下からすべてのPythonスクリプトを検索
find . -name "*.py"

# 特定のプレフィックスから始まる設定ファイルを検索
find /etc -name "nginx*.conf"

# 大文字・小文字を無視して画像ファイルを検索(.jpg, .JPG, .Jpg にマッチ)
find ./images -iname "*.jpg"

注意点として、-name に指定するパターンは必ず ダブルクォート "..." またはシングルクォート '...' で囲む 必要があります。クォートを忘れると、シェルが事前にファイル名を展開してしまい、予期せぬエラーの原因になります(詳細は後述の落とし穴セクションを参照)。

ファイル形式(通常ファイル・ディレクトリ)で絞り込む(-type f / -type d)

Linuxではファイルとディレクトリが同名で存在したり、スクリプト実行時に対象を「通常ファイルのみ」に限定したいケースが多々あります。その際は -type オプションを活用します。

# 通常ファイル(file)のみを検索
find . -type f -name "app*"

# ディレクトリ(directory)のみを検索
find . -type d -name "logs"

# シンボリックリンク(link)のみを検索
find /usr/local/bin -type l

実務で非常によくあるユースケースが、Webサーバー公開ディレクトリの一括権限設定です。ディレクトリには実行権限(進入権限)が必要ですが、通常ファイルには不要です。以下のように使い分けるのがプロの現場作法です。

# ディレクトリのみ 755 に設定
find /var/www/html -type d -exec chmod 755 {} +

# 通常ファイルのみ 644 に設定
find /var/www/html -type f -exec chmod 644 {} +

パーミッション計算や権限設計の基礎については、別記事 【Linux】chmodコマンドの使い方とパーミッション設定|755・644の計算と記号モード解説 で詳しく解説しています。

検索する階層の深さを制限する(-maxdepth / -mindepth)

find はデフォルトでサブディレクトリの最深部まで再帰的に探索します。しかし、大規模なファイルシステムや巨大なプロジェクト(node_modules や .git 配下など)では、検索に膨大な時間がかかってしまいます。階層の深さを制限するには -maxdepth と -mindepth を使用します。

# カレントディレクトリ直下(深さ1)のみを検索(サブディレクトリは探索しない)
find . -maxdepth 1 -name "*.sh"

# 深さ2階層まで(直下および1つ下のサブディレクトリまで)を探索
find /var/log -maxdepth 2 -type f -name "*.log"

# 直下を除外し、深さ2以上のサブディレクトリ配下のみを探索
find . -mindepth 2 -type f -name "*.env"

現場の鉄則 として、-maxdepth や -mindepth は検索パスの直後、他の検索条件(-name 等)よりも前に記述してください。GNU find では後ろに記述しても動作しますが、警告が出ることがあります。

更新日時・タイムスタンプで絞り込む(-mtime / -mmin / -newer)

ログのローテーションや定期バックアップのクリーンアップなど、時間条件による絞り込みはシステム運用の生命線です。find には日数単位の -mtime と分単位の -mmin が用意されています。

-mtime の数値の前に付ける符号(+、-、なし)には厳密なルールがあります。

  • -mtime +7 : 最終更新が 「7日超前(8日以上前)」 のファイル
  • -mtime -7 : 最終更新が 「直近7日以内」 のファイル
  • -mtime 7 : 最終更新が 「ちょうど7日前(7日〜8日前までの24時間)」 のファイル
# 30日以上更新されていない古いログファイルを抽出
find /var/log/app -type f -name "*.log" -mtime +30

# 直近24時間以内(1日以内)に更新された設定ファイルを調査
find /etc -type f -mtime -1

# 直近10分以内に作成・更新されたファイルを緊急特定(障害発生時のトレース)
find /tmp -type f -mmin -10

# 特定の参照ファイル(deploy.flag)より後に更新されたファイルのみ抽出
find /var/www -type f -newer /tmp/deploy.flag

ファイルサイズで探す(-size +100M)

サーバーのディスク容量アラートが発生した際、どのファイルが容量を食い潰しているかを突き止めるには -size オプションが最も手軽です。

単位の指定方法は以下の通りです。k(キロバイト)のみ小文字で、M(メガバイト)や G(ギガバイト)は大文字で指定します。

  • c: バイト
  • k: キロバイト(KB)
  • M: メガバイト(MB)
  • G: ギガバイト(GB)
# 100MBを超える巨大ファイルを検索
find /var -type f -size +100M

# 1GB以上のファイルをリストアップし、容量が大きい順にソートして表示
find / -type f -size +1G -exec ls -lh {} + 2>/dev/null | sort -k5,5 -h -r | head -n 10

# 空ファイル(サイズ0バイト)を検索
find . -type f -empty

複数条件の組み合わせ(AND: -a / OR: -o / NOT: !)

条件を複数組み合わせることで、精度の高いピンポイント抽出が可能になります。

  • AND(論理積) : 条件をスペースで並べるか、明示的に -a を指定。
  • OR(論理和) : -o を指定。優先順位を明確にするため丸括弧 ( ... ) で囲みます。
  • NOT(否定) : ! または -not を指定。
# 【AND】通常ファイル かつ 拡張子が .log かつ 10MB以上
find /var/log -type f -name "*.log" -size +10M

# 【OR】拡張子が .jpg または .png のファイル
find ./images -type f ( -name "*.jpg" -o -name "*.png" )

# 【NOT】Git関連ディレクトリ(.git)を除外して全スクリプトを検索
find . -type f -name "*.sh" ! -path "*/.git/*"

# 【実務複合例】ログまたは一時ファイルで、かつ30日以上前のものを抽出
find /data -type f ( -name "*.log" -o -name "*.tmp" ) -mtime +30

検索結果に対する一括アクション(実務自動化)

目的のファイルをリストアップできたら、次はその結果に対してコマンドを実行し、運用の自動化を図ります。手作業で1つずつコマンドを打つ必要はありません。

-execでコマンドを直接実行する({} + と {} ; の違い)

-exec は、検索にヒットしたファイルパスをプレースホルダー {} に代入してコマンドを実行する強力なアクションです。ここで必ず押さえておくべきなのが、末尾の ; と + の挙動の違い です。

# 方式A: 末尾が ; の場合(個別実行)
find . -type f -name "*.log" -exec gzip {} ;

# 方式B: 末尾が + の場合(一括引数渡し・現場推奨)
find . -type f -name "*.log" -exec gzip {} +

何が違うのか?

  • ;(個別実行) : ファイルが1,000個見つかった場合、gzip file1, gzip file2… と 1,000回プロセスを起動 します。プロセス生成コストが非常に高く、動作が遅くなります。
  • +(一括実行) : ファイルが1,000個見つかった場合、gzip file1 file2 file3 ... のように 引数を可能な限りまとめて1回のコマンドで起動 します。実行速度が数十倍から数百倍向上します。

特別な理由がない限り、-exec には {} + を使用するのが実務の定石 です。なお、削除や変更の前に1ファイルずつユーザーに実行確認を取りたい場合は -ok アクションが便利です。

# 実行前に1件ずつ y/n の確認プロンプトを表示する
find . -type f -name "*.bak" -ok rm {} ;

xargsと連携して高速一括処理する(-print0 と xargs -0 の重要性)

パイプラインを組んで後続コマンドにファイル一覧を渡す際、最もよく使われるのが xargs コマンドとの連携です。ここで絶対に外してはならないのが -print0 と xargs -0 のペア です。

# 【鉄板ペア】ヌル文字区切りで安全にxargsへ渡す
find . -type f -name "*.log" -print0 | xargs -0 grep "FATAL_ERROR"

なぜこの指定が必須なのでしょうか?通常の find は改行やスペースでファイル名を出力します。もし My Document.txt や backup-archive.log のように ファイル名に半角スペースや改行が含まれている場合 、通常の xargs はスペースを区切り文字と誤認し、「My」と「Document.txt」という別々のファイルとして扱ってしまい、コマンドが失敗します。

-print0 はファイル名の区切りとしてヌル文字(\0)を出力し、xargs -0 はヌル文字を区切りとして解釈します。ファイル名に空白・特殊文字・日本語が含まれていても100%安全に処理できます。

xargs の詳細なオプションや並列処理(-P)の活用テクニックについては、並列処理でスクリプトを加速するためのxargsとGNU parallel活用ガイド を参照してください。また、テキスト内容の検索については 【完全早見表】grepコマンドの使い方と主要オプション逆引き一覧 も併せてご活用ください。

条件に一致したファイルを安全に一括削除する(-delete の注意点)

GNU find には、マッチしたファイルを直接消去できる -delete アクションが備わっています。-exec rm {} + と比較して外部の rm プロセスを起動しないため、極めて高速に動作します。

しかし、-delete の使用には 致命的な落とし穴 が存在します。それは オプションを記述する順番 です。

# 【超危険・絶対NG!】-delete を条件より前に書いた例
find . -delete -name "*.tmp"

# 【正しい安全な記述】検索条件の「最後」に -delete を配置する
find . -type f -name "*.tmp" -delete

find はオプションを左から右へ順番に評価します。もし -delete を先頭に書いてしまうと、 「条件判定が行われる前に、カレントディレクトリ内の全ファイルを無条件に削除する」 という恐ろしい大惨事が発生します。

現場での安全削除プロトコル(2ステップ):

  • ステップ1(事前検証) : まずは -delete を付けずに実行し、削除対象のファイル一覧を目視で確認する。
    find /tmp -type f -name "*.tmp" -mtime +7
  • ステップ2(本番削除) : 出力結果が正しいことを確かめた上で、末尾に -delete を追加して実行する。
    find /tmp -type f -name "*.tmp" -mtime +7 -delete

不測のデータ消失を防ぐ安全なファイル操作の心構えについては、Bashで安全にcpとrmを使用する方法:データを失わないためのベストプラクティス もぜひご覧ください。

現場でよくあるエラーと落とし穴

実務で find コマンドを実行した際、思い通りに動かない典型的なトラブルと解決策をまとめました。

パーミッションエラー(Permission denied)を無視・除外する方法(2>/dev/null)

ルートディレクトリ(/)やシステムディレクトリ配下を一般ユーザーで検索すると、アクセス権のないディレクトリに進入しようとして画面が Permission denied のエラーログで埋め尽くされます。その結果、本当に見つけたい検索結果がスクロールの彼方に流れてしまいます。

# 【問題の例】画面が Permission denied のエラーで埋まる
$ find / -name "my_app.conf"
find: '/root': Permission denied
find: '/var/spool/cron/atjobs': Permission denied
...(大量のエラー)...

# 【解決策】標準エラー出力(ファイルディスクリプタ 2)を /dev/null に破棄する
find / -name "my_app.conf" 2>/dev/null

2>/dev/null を末尾に付与することで、権限不足などのエラーメッセージのみが破棄され、ヒットした正常な検索結果だけをクリーンに表示できます。

ワイルドカード展開の罠(クォート引用必須)

初心者が最も高い確率で遭遇する謎のエラーがこちらです。

# カレントディレクトリに a.txt と b.txt がある状態で以下を実行
$ find . -name *.txt
find: paths must precede expression: `b.txt'

なぜこのエラーが発生するのでしょうか?理由は 「Bashシェルが find コマンドを実行する前に *.txt をファイル名に展開してしまうから」 です。

カレントディレクトリに a.txt と b.txt が存在する場合、シェルはコマンドラインを解釈して find . -name a.txt b.txt という形に書き換えてから find に渡します。find にとって b.txt は理解不能な第2の引数となり、構文エラーを引き起こします。

# 【正しい書き方】必ずシングルまたはダブルクォートで保護する
find . -name "*.txt"
find . -name '*.txt'

クォートで囲むことで、シェルによる事前展開を阻止し、ワイルドカード文字列そのものを find コマンドの内部評価エンジンに安全に引き渡すことができます。

まとめ & 関連記事

今回は、Linux実務に欠かせない find コマンドの使い方、主要オプション早見表、条件絞り込みパターンから一括処理自動化までを網羅的に解説しました。

最後に、日々のファイル操作を自動化するための 3つの心得 を整理しておきましょう。

  • 1. 探索空間を最小化する : 大規模システムでは -maxdepth や -type を活用し、無駄なファイル走査を未然に防ぐ。
  • 2. 条件を組み合わせて一撃で特定する : ファイル名(-name)、日時(-mtime)、サイズ(-size)を論理演算子で組み合わせ、目的のファイルをピンポイントで絞り込む。
  • 3. 安全性を最優先に一括処理する : xargs との連携は -print0 | xargs -0、一括実行は -exec ... + を基本とし、-delete は必ず事前検証を行ってから末尾で実行する。

find コマンドを手足のように扱えるようになれば、サーバー上のファイル探索や定期バッチ処理の効率は何倍にも跳ね上がります。ぜひ日々の実務に役立ててください。

あわせて読みたい関連記事

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント