findは、ファイルやディレクトリを名前・種類・サイズ・更新日などの条件で検索するLinuxの定番コマンドです。grepがファイルの「中身」を検索するのに対し、findは「ファイルそのもの」を探します。「特定の拡張子のファイルを全部探す」「1週間以上前の古いファイルを見つける」「サイズの大きいファイルを探す」といった用途で活躍します。
つまずきやすいのは、パターンをクォートで囲むこと(囲まないとシェルが先に展開してしまう)、-nameは大文字小文字を区別すること、そして-mtimeのプラス・マイナスの意味です。また、-deleteは取り消せないため注意が必要です。この記事では、実機のLinux(WSLのDebian)で実際にコマンドを動かしながら、findの使い方を整理します。
- 基本は
find 検索場所 -name "パターン"。標準でサブフォルダも再帰検索します。 -type fでファイルのみ、-type dでディレクトリのみに絞れます。-nameは大文字小文字を区別。無視するなら-inameです。-size +1Mで1MBより大きい、-mtime -7で7日以内、+7で7日より古い。- 見つけたファイルに処理するには
-exec コマンド {} \;やxargsを使います。 -deleteは取り消せないので、先に検索だけで対象を確認します。
中身の検索はgrepコマンド、ほかの基本コマンドはよく使うLinuxコマンドまとめ、ディレクトリ移動はcdコマンドもあわせて参考になります。
findの基本(-name・再帰)
もっとも基本的な使い方は、find 検索場所 -name "パターン"です。findは指定した場所以下を自動的に再帰検索します(grepと違い-rは不要)。
# カレントディレクトリ以下から .txt ファイルを探す find . -name "*.txt" # 出力例(サブフォルダも自動で検索される) # ./a.txt # ./big.txt # ./sub/c.txt # 特定のディレクトリを検索 find /var/log -name "*.log"
実機でも、find . -name "*.txt"はカレントのa.txtだけでなく、サブフォルダのsub/c.txtも見つけました。findは標準でサブフォルダまで再帰検索する点が、-rが必要なgrepとの違いです。検索場所の.はカレントディレクトリを表します。パターンは"*.txt"のようにクォートで囲むのが重要です。囲まないと、シェルが先に*.txtを展開してしまい、意図しない動作になることがあります。
種類で絞る(-type)・大小無視(-iname)
ファイルだけ、あるいはディレクトリだけを探したいときは-typeを使います。-type fがファイル、-type dがディレクトリです。また、-nameは大文字小文字を区別するため、区別したくないときは-inameを使います。
# ファイルだけを検索 find . -type f # ディレクトリだけを検索 find . -type d # -name は大文字小文字を区別(*.log は b.LOG にヒットしない) find . -name "*.log" # -iname なら大文字小文字を無視(b.LOG もヒット) find . -iname "*.log"
実機で確認したところ、b.LOGというファイルがある状態でfind . -name "*.log"は何もヒットしませんでした(.logと.LOGを区別するため)。一方、find . -iname "*.log"はb.LOGを正しく見つけました。Linuxは大文字小文字を区別するので、拡張子の大小が混在する環境では-inameが安全です。-type fはファイルだけ、-type dはディレクトリだけに絞り込みます。たとえば「ディレクトリは除いてファイルだけ消したい」「空のディレクトリだけ探したい」といったときに、-typeで対象を明確にできます。-typeと-nameは組み合わせて使えます(find . -type f -name "*.txt")。
サイズ・更新日で絞る(-size / -mtime)
findは、ファイルのサイズや更新日でも検索できます。大きなファイルを探したり、古いファイルを見つけたりするのに便利です。-sizeはサイズ、-mtimeは更新からの日数です。
# 1MB より大きいファイル(+ は「より大きい」) find . -size +1M # 100KB より小さいファイル find . -size -100k # 7日「以内」に更新されたファイル(-7 はマイナス) find . -mtime -7 # 7日「より前」に更新された古いファイル(+7 はプラス) find . -mtime +7 # 組み合わせ: /tmp の7日より古い .tmp ファイル find /tmp -name "*.tmp" -mtime +7
実機で確認したところ、10日前に更新したファイルと今日のファイルがある状態で、find . -mtime +7は7日より古いファイル(10日前のもの)を、find . -mtime -7は7日以内のファイル(今日のもの)を見つけました。+7は「7日より前(古い)」、-7は「7日以内(最近)」という意味で、符号を間違えると逆の結果になります。古いログの掃除などでは-mtime +N(N日より古い)をよく使います。サイズの-sizeも同様で、+1Mは「1MBより大きい」、-1Mは「1MBより小さい」です。単位はk(KB)・M(MB)・G(GB)が使えます。古いファイルの削除など、削除を伴う操作では、必ず先に検索だけで対象を確認してから実行してください。
空ファイル(-empty)・階層(-maxdepth)
中身が空のファイルやディレクトリは-emptyで探せます。また、再帰の深さを制限したいときは-maxdepthを使います。-maxdepth 1なら、サブフォルダに入らず直下だけを検索します。
# 空のファイル・ディレクトリを探す find . -empty # サブフォルダに入らず、直下だけを検索(-maxdepth 1) find . -maxdepth 1 -name "*.txt" # 2階層までに制限 find . -maxdepth 2 -type f
実機でも、find . -emptyで空のファイルと空のディレクトリの両方が見つかり、find . -maxdepth 1 -name "*.txt"はサブフォルダの中を見ずに直下の.txtファイルだけを返しました。findは標準ですべての階層を検索しますが、-maxdepthで深さを制限すると、検索範囲を絞れて速くなります。「直下だけ見たい」「深くもぐりすぎないようにしたい」ときに便利です。
見つけたファイルに処理する(-exec / xargs)
findの真価は、見つけたファイル1つ1つに対してコマンドを実行できることです。-exec コマンド {} \;の{}が、見つかった各ファイルに置き換わります。大量のファイルにはxargsを使う方法もあります。
# 見つけた各ファイルにコマンドを実行({} がファイル名に置き換わる)
find . -name "*.txt" -exec wc -c {} \;
# xargs を使う書き方(まとめて渡すので高速)
find . -name "*.txt" | xargs wc -l
# 例: 古いログを gzip で圧縮する
find /var/log -name "*.log" -mtime +30 -exec gzip {} \;
実機でも、find . -name "*.txt" -exec wc -c {} \;で、見つかった各.txtファイルのバイト数が表示されました。{}が見つかったファイル名に、\;がコマンドの区切りを表します(;はシェルに解釈されないよう\;とエスケープします)。xargsを使うと、見つかったファイルをまとめてコマンドに渡すため、ファイル数が多いときに高速です。「見つけて、コピー・移動・圧縮・削除する」という一連の処理が、find1つで自動化できます。
削除(-delete)の注意
findには、見つけたファイルを削除する-deleteがあります。便利ですが取り消せないため、必ず先に検索だけを実行して対象を確認してから使います。
# 危険: いきなり -delete しない
# STEP1: まず検索だけして、消える対象を確認する
find . -name "*.tmp"
# STEP2: 表示された内容に問題なければ -delete を付ける
find . -name "*.tmp" -delete
# -exec rm でも削除できる(-delete のほうが安全で確実)
# find . -name "*.tmp" -exec rm {} \;
実機で確認したところ、find . -name "*.tmp" -deleteで該当ファイルが正しく削除されました(実行後、.tmpファイルは0個)。ただし削除は取り消せません。条件を1つ間違えると、意図しないファイルまで消えてしまう恐れがあります。必ず先に-deleteを付けずに検索だけを実行し、表示された一覧に消したくないファイルが含まれていないことを確認してから、-deleteを付けて本実行してください。とくにfind / ...のようにルートから検索する場合は要注意です。なお-exec rm {} \;でも削除できますが、-deleteのほうが安全で高速です。心配なら、削除ではなく別フォルダへの移動(-exec mv {} /path/ \;)から始めるとよいでしょう。
主なオプション一覧
findでよく使うオプションをまとめます。
| オプション | 働き |
|---|---|
-name "パターン" |
名前で検索(大小区別) |
-iname |
名前で検索(大小無視) |
-type f / -type d |
ファイル / ディレクトリのみ |
-size +1M |
サイズで絞る(+大きい / -小さい) |
-mtime +7 / -7 |
更新日(+古い / -以内) |
-empty |
空のファイル・ディレクトリ |
-maxdepth N |
検索する階層を制限 |
-exec コマンド {} \; |
見つけた各ファイルに実行 |
-delete |
削除(取り消し不可・要確認) |
よくある失敗
パターンをクォートで囲まない
シェルが先に展開してしまいます。-name "*.txt"のように囲みます。
-nameで大文字小文字が合わず見つからない
-nameは区別します。無視するなら-inameを使います。
-mtimeの+と-を逆にする
+NはN日より古い、-NはN日以内です。古いファイルは+Nです。
確認せずに-deleteする
取り消せません。先に検索だけして対象を確認してから削除します。
-execの\;を忘れる
-execはコマンドの終わりに\;が必要です。
よくある質問
find 検索場所 -name "*.拡張子"を使います。たとえばfind . -name "*.txt"で、カレントディレクトリ以下のすべての.txtファイルを探せます。findは標準でサブフォルダまで再帰検索するため、grepと違い-rは不要です。大文字小文字を無視するなら-inameを使います。-mtime、サイズは-sizeを使います。find . -mtime +7で7日より古いファイル、find . -size +1Mで1MBより大きいファイルが見つかります。+は「より古い・より大きい」、-は「以内・より小さい」を表します。-exec コマンド {} \;を使います。{}が見つかった各ファイル名に置き換わります。たとえばfind . -name "*.log" -exec gzip {} \;で、見つけたログを順に圧縮できます。ファイル数が多いときはfind ... | xargs コマンドのほうが高速です。-nameは大文字小文字を区別します。区別したくないときは-inameを使ってください。find . -iname "*.log"なら、.logでも.LOGでもヒットします。Linuxは大文字小文字を区別するため、拡張子の大小が混在する環境では-inameが安全です。-deleteを付けずに検索だけを実行し、消える対象を確認してください。表示された一覧に問題がなければ、find . -name "*.tmp" -deleteのように-deleteを付けて実行します。削除は取り消せないため、条件の確認が重要です。心配なら削除ではなく移動から始めましょう。まとめ
- 基本は
find 場所 -name "パターン"。標準で再帰検索します(-r不要)。 -type f/dで種類、-inameで大小無視の名前検索。-size +1M・-mtime +7でサイズ・更新日を指定(+は大きい/古い)。-exec コマンド {} \;やxargsで、見つけたファイルに処理します。-deleteは取り消し不可。先に検索で対象を確認してから使います。
findは、Linuxでファイルを探すときの基本コマンドです。grepが「中身」を探すのに対し、findは「ファイルそのもの」を名前・サイズ・日付で探します。「-mtimeの符号」「-deleteは確認してから」の2点を押さえ、-execと組み合わせれば、ファイル整理や定期メンテナンスを効率よく自動化できます。
