FINDコマンド

FINDの特徴

FINDコマンドは、ディレクトリ階層内のファイルやディレクトリを検索するツールである。このコマンドは以下のような特徴がある。条件を満たすファイルやディレクトリを見つけ出すことができ、検索条件を柔軟に指定できる。また、サブディレクトリを含めた再帰的な検索も可能であるとともに、一致したファイルへアクションを実行することもできる。

以下のファイルがあるディレクトリでいくつかfindコマンドを試してみる。

ll --time-style long-iso
(out)-rw-r--r-- 1 user user 10000 2025-02-21 00:04 file1.txt
(out)-rw-r--r-- 1 user user   500 2025-02-21 00:03 file2.txt
(out)-rw-r--r-- 1 user user    50 2025-02-21 00:02 file3.txt
(out)-rw-r--r-- 1 user user  1350 2025-02-21 00:01 file4.txt
(out)-rw-r--r-- 1 user user  5000 2025-02-21 00:00 file5.txt
(out)-rw-r--r-- 1 user user  1001 2025-02-20 23:59 file6.txt
(out)-rw-r--r-- 1 user user     0 2025-02-20 23:58 file7.txt
(out)-rw-r--r-- 1 user user   420 2025-02-20 23:57 file8.txt
(out)-rw-r--r-- 1 user user  1200 2025-02-20 23:56 file9.txt
find -size +1000c # サイズが1000バイト超の項目を探す
(out)./file1.txt
(out)./file4.txt
(out)./file5.txt
(out)./file6.txt
(out)./file9.txt
find -size +1k # サイズが1KiB超の項目を探す
(out)./file1.txt
(out)./file4.txt
(out)./file5.txt
(out)./file9.txt
date --iso-8601="seconds" # 本コマンドは2/21に実行した
(out)2025-02-21T13:53:18+09:00
find -daystart -mtime -1 # 更新日が今日の項目を探す
(out)./file1.txt
(out)./file2.txt
(out)./file3.txt
(out)./file4.txt
(out)./file5.txt
find -name '*3*' # 名前に3が含まれるファイルを探す
(out)./file3.txt
find -regex '.*[3-5].*' # パスに3~5が含まれる項目を探す
(out)./file3.txt
(out)./file4.txt
(out)./file5.txt

結果の表示順

findコマンドの結果はinode番号順に表示される。並び替えを行いたいときは他のコマンドへパイプで渡す。ファイル名以外で並び替えたいときは、後述のprintを使用して並び替えに使いたいキー情報を出力すると良い。

構文

find [オプション] [検索開始場所] 式...

findコマンドは検索開始場所の配下にある各ファイルについて式を評価する。デフォルトでは式の結果が真であるものを標準出力へ出力する。

式は検索方法を定めるものである。式はテストやアクションなどに分類される。

アクション

対象に対して何らかの操作を行う式をアクションと呼ぶ。主なアクションを示す。

アクション説明実行後の値
-print
-print0
ファイル名を標準出力に改行区切りで出力する。
print0はヌル文字(\0)区切りにする。
-fprint filename
-fprint0 filename
ファイル名をfilenameに改行区切りで出力する。
print0はヌル文字(\0)区切りにする。
-exec指定したコマンドを実行する。
コマンド中の{}はファイル名で置き換えられる。
コマンドはfindを実行したディレクトリで行われる。
コマンドの戻り値が0なら真
-execdir command;指定したコマンドを実行する。
コマンド中の{}はファイル名で置き換えられる。
コマンドはファイルがあるディレクトリで行われる。
コマンドの戻り値が0なら真
-ok-execに似ているが、実行前にユーザに確認する。ユーザが実行を拒否したら偽
-okdir command;-execdirに似ているが、実行前にユーザに確認する。ユーザが実行を拒否したら偽
-printf format
-fprintf filename format
見つかったファイルの情報を指定したフォーマットで出力する。
fprintfはファイルに出力する。
-ls
-fls filename
ファイルをls -dils形式で標準出力に表示する。
flsはファイルに出力する。
-pruneディレクトリを探索対象から除外する。
-delete見つかったファイルを削除する。削除が成功したら真
-quitすぐに終了する。-
デフォルトアクション

findはデフォルトで式が真となったファイルに対して-printアクションを実行する。ただし式の中に-pruneと-quitを除いたアクションが含まれている場合はデフォルトの-printを実行しない。

オペレータ

オペレータは式と組み合わせて使う。

意味
-not expression
! expression
式の結果を否定する。
expresion1 expression2
expression1 -a expression2
expression1 -and expresion2 (非推奨)
式をAND結合する。
-a、-andで明示できる。
expression1 -o expression2
expression1 -or expresion2 (非推奨)
式をOR結合する。
( expression1 -o expression2 ) -a expression3式の評価順序を指定する。
expression1, expression2式を列挙する。
expression1、expression2の順に評価され、expression2の値を返す。expression1の結果は無視される。

テスト

対象を評価するのがテスト式である。

条件説明
-name filename
-iname filename
ファイル名が指定のパターンと一致するファイルを検索する。inameでは大文字と小文字を区別しない。
パターンではシェルのワイルドカード(.と*)が使用できる。
-regex regexパスが正規表現と一致する。ファイル名だけでなく、パスも検索対象であり、完全一致であることに注意する。
-regextype regexmodeと併用すると正規表現の種類を指定できる。
-type type対象の種類で検索する。
f(ファイル)、d(ディレクトリ)、l(シンボリックリンク)など
-size sizeサイズで検索する。単位として以下が使用可能。
b(ブロック:単位省略時のデフォルト)c(バイト)k(キロバイト)M(メガバイト)G(キロバイト)
-mtime days
-ctime days
-atime days
最終更新日時(mtime)、最終変更日時(ctime)、最終アクセス日時(atime)で検索する。

最終変更日時

本稿ではmtimeを最終更新日時、ctimeを最終変更日時としている。

パス・ファイル名
-name/-iname

ファイル名が指定のワイルドカードパターン(.と*が使用可能)と一致する項目を検索する。inameは大文字と小文字を区別しない。

find -name '*1*'
(out)./search1.txt
-path/-ipath/-wholename/-iwholename

※互換性の観点から-path/ipathの利用が推奨される。

パスが指定のワイルドカードパターンと一致する項目を検索する。findにおけるパスは、検索する項目の絶対パスではなく検索開始場所から見たパスを指していることに注意すること。

find .
(out).
(out)./abc
(out)./abc/123
find abc
(out)abc
(out)abc/123
find . -path '*/abc/123'
(out)./abc/123
find abc -path '*/abc/123'
-regex/-iregex

パスが正規表現と一致するか検索する。ファイル名だけでなく、パスも検索対象となる。iregexは大文字と小文字を区別しない。

find -regex '.*[7-9].*'
(out)./search9.txt
(out)./search8.txt
(out)./search7.txt

パス全体が正規表現に一致するかを評価するため、789のどれかがパスに含むものを探すときは.*[7-9].*のように前後に.*を付けなければならない。

-regextypeオプションを使用すると正規表現の種類を指定できる。posix-extendedを使用すると拡張正規表現が使用できる。

find -regex ".*\(7\|8\).*"
(out)./search8.txt
(out)./search7.txt
find -regextype posix-extended -regex ".*(7|8).*"
(out)./search8.txt
(out)./search7.txt
日時属性
-mtime/-ctime/-atime/-mmin/-cmin/-amin

現在時刻を基準とした、最終更新日時(Modified)、最終変更日時(Changed)、最終アクセス日時(Accessed)の経過日数または経過分数が条件を満たすか指定する。

経過日数のイメージ
経過分数のイメージ
指定値xtimexmin
n経過時間がn日以上n+1日未満経過時間がn-1分以上n分未満
+n経過時間がn日以上経過時間がn-1分以上
-n経過時間がn日未満またはn日になった瞬間経過時間がn分未満

更新日時が24時間~72時間のものを検索するときは、「経過時間が1日以上かつ3日未満となるので」なので-xtime +1 -mtime -3のようになる。

-daystart

-daystartオプション以降に現れる-xtimeでは、経過時間ではなく「00:00に達したら1日経過した」と考える。例えば現在時刻が2/10のときは以下のようになる。

タイムスタンプの範囲経過日数
2/11 00:00:00 ~ 2/10 00:00:010日
2/10 00:00:00 ~ 2/09 00:00:011日
2/09 00:00:00 ~ 2/08 00:00:012日
daystartのイメージ
(本表は少数単位の秒数を考慮していない)

-Nのようにマイナスが付けられた場合は「経過日数がN日に満たないまたはN日になった瞬間」と解釈される。つまり-1なら当日の00:00:00以降が条件を満たすことになるので、要は「今日の日付」という意味である。実際にfile1が表示されなくなる実行例を示す。

date --iso-8601="seconds"
(out)2025-02-22T03:24:37+09:00
find -mtime -1 -printf '%TF %TX %p\n'
(out)2025-02-21 23:59.0000000000 ./file1.txt
(out)2025-02-22 00:00.0000000000 ./file2.txt
(out)2025-02-22 00:01.0000000000 ./file3.txt
find -daystart -mtime -1 -printf '%TF %TX %p\n'
(out)2025-02-22 00:00.0000000000 ./file2.txt
(out)2025-02-22 00:01.0000000000 ./file3.txt
-newer/-anewer/-cnewer

参照先のタイムスタンプと比べて新しいかを調べる。-newerは最終更新日時、-anewerは最終アクセス日時、-cnewerは最終変更日時を比べる。

find -newer file3.txt -printf '%TF %TT %p\n'
(out)2025-02-21 00:04:00.0000000000 ./file1.txt
(out)2025-02-21 00:03:00.0000000000 ./file2.txt
-newerXY

-newerXY 参照先のようにし、参照先のYのタイムスタンプとXのタイムスタンプを比べて新しければTrueと見なす。XYには以下のいずれかが入る。

a最終アクセス日時(atime)
B生成日時(Birth Time)
c最終変更日時(ctime)
m最終更新日時(mtime)
t参照先をパスではなく時刻を表す文字列と見なす。
-newermtのように、tは必ずYの位置になる。
時刻を表す文字列の例:"2025-02-22 02:39" "Feb 1" "Feb 22, 2025 02:38"

たとえば-newercm であれば、ファイルの属性または内容の更新日時で比較される。-newerは-newermm、-cnewerは-newercm、-anewerは-neweramと等しい。

find -neweraa file2.txt # file2.txtの最終アクセス日時より、最終アクセス日時が新しいファイルを探す
(out)./file1.txt
(out)./file3.txt
find -newerma file2.txt find # file2.txtの最終アクセス日時より、最終更新日時が新しいファイルを探す
(out)./file3.txt
-used

対象の最終更新日時を基準として、最終アクセス日時がn日経過後かを調べる。長期アクセスが無いファイルを探すのに役立つ。

サイズ
-size

サイズを条件に探す。デフォルトではブロック単位であり、なおデフォルトのブロックの単位は通常512バイトだが環境により異なりうるが、bは常に512バイトである。

  • 単位としてb(ブロック)c(バイト)k(キビバイト)M(メビバイト)G(ギビバイト)が利用できる。
    • デフォルトではブロックで通常512バイトだが環境により異なりうる。ただしbは常に512バイトである。
  • +は超過、-は未満として扱われる。
  • 単位に満たない端数は切り上げられる。-size 1kはサイズが0キビバイト超1キビバイト以下を意味し、1バイトから1024バイトが一致する。
  • -size -Nunitは切り上げられた結果がNユニット未満かどうかで判定される。+も同様である。
ファイルサイズ-0k0k+0k-1k1k+1k-2k2k+2k
0バイト
1バイト
1023バイト
1024バイト
1025バイト
2047バイト
2048バイト
2049バイト
ll -Sr
(out)-rw-r--r-- 1 user user    0 Feb 22 15:06 0b.txt
(out)-rw-r--r-- 1 user user    1 Feb 22 15:10 1b.txt
(out)-rw-r--r-- 1 user user 1023 Feb 22 15:02 1kb-1.txt
(out)-rw-r--r-- 1 user user 1024 Feb 22 15:02 1kb.txt
(out)-rw-r--r-- 1 user user 1025 Feb 22 15:02 1kb+1.txt
(out)-rw-r--r-- 1 user user 2047 Feb 22 15:04 2kb-1.txt
(out)-rw-r--r-- 1 user user 2048 Feb 22 15:04 2kb.txt
(out)-rw-r--r-- 1 user user 2049 Feb 22 15:04 2kb+1.txt
find -size 2k # これは2キビバイト → 1024バイト超2048バイト以下
(out)./1kb+1.txt
(out)./2kb-1.txt
(out)./2kb.txt
find -size -2k # これは2キビバイト未満 → 1キビバイト以下 → 1024バイト以下
(out)./0b.txt
(out)./1b.txt
(out)./1kb-1.txt
(out)./1kb.txt
タイプ
-type

-type Xでアイテムのタイプを指定する。

オプションの値説明
bブロックデバイスファイル
cキャラクターデバイスファイル
dディレクトリ
f通常のファイル
lシンボリックリンク
p名前付きパイプ(FIFO)
sソケットファイル
Dドアファイル(Solaris専用)

xtype

シンボリックリンクの時に一部挙動が異なる-xtypeもある。たとえば、-P -xtype X(Xはlを除く上記タイプ指定のいずれか)とすると、シンボリックファイルが指すファイルの種類がXかどうか検査する。

所有者・グループ
-user/-nouser/-group/-nogroup

所有者またはグループの名前かIDが一致する(またはしない)。数字でIDを指定する場合でも+/-はサポートされない。

-uid/-gid

所有者IDまたはグループIDが一致する。+/-がサポートされる。

パーミッション
-readable/-writable/-executable

findを実行したユーザが読み込み/書き込み/実行権限を持つか検査する。

-perm

findを実行したユーザから見たパーミッションを検査する。

  • -perm 664はパーミッションが664であるときに一致する。
  • -perm -664はパーミッションが664よりあるときに一致する。例えば674、777などは一致する。
  • -perm /222は誰かが読み込み権限を持つときに一致する。

検索範囲

findコマンドは検索開始場所からディレクトリツリーをたどってファイルを探す。検索開始場所が指定されなかった場合は.(カレントフォルダ)とみなされる。

階層の深さ

-mindepth/-maxdepth

たどる階層の深さを指定する。0では今の階層のみを探す。

tree
(out).
(out)└── d1
(out)    └── d2
(out)        └── d3
(out)            └── d4
(out)                └── d5
(out)                    └── d6
(out)
(out)7 directories, 0 files
find -mindepth 3 -maxdepth 5
(out)./d1/d2/d3
(out)./d1/d2/d3/d4
(out)./d1/d2/d3/d4/d5

指定サブフォルダの除外

アクションで紹介したpruneは検索している対象がディレクトリである場合、そのディレクトリの中は探索範囲から除外し、式の結果は真となるものであった。以下のように他の式と組み合わせると、特定のディレクトリを除外できる。

find -path 除外するパス -prune -o -print

実際に除外して探索する例を示す。

tree
(out).
(out)└── d1
(out)    ├── 1-2
(out)    └── d2
(out)        ├── 2-1
(out)        ├── 2-2
(out)        └── d3
(out)            ├── 3-1
(out)            ├── 3-2
(out)            └── d4
(out)                ├── 4-1
(out)                └── 4-2
find -path ./d1/d2/d3 -and -prune -o -print
(out)./d1/1-2
(out)./d1/d2
(out)./d1/d2/2-1
(out)./d1/d2/2-2

-andはわかりやすくするために付けており、無くても同じ結果になる。

  • ディレクトリ./d1/d2が検索対象の項目に選ばれたとき、-path ./d1/d2/d3 -and -prune -o -printは以下のように評価される。
    • -path ./d1/d2/d3はfalseである。評価式は-false -and -prune -o -print となる。
    • AND条件で左辺がfalseであるため右辺は-pruneは評価されない。-false -or -printという途中結果となる。
    • OR条件で左辺がfalseであるため、右辺が評価される。右辺は-printであるため./d1/d2は出力される。
  • ディレクトリ./d1/d2/d3が検索対象の項目に選ばれたとき、-path ./d1/d2/d3 -and -prune -o -printは以下のように評価される。
    • -path ./d1/d2/d3はtrueである。評価式は-true -and -prune -o -print となる。
    • AND条件の左辺がtrueであるため右辺-pruneも評価される。./d1/d2/d3はディレクトリであるため、検索対象から外れた上でTrueとなる。-true -or -printという途中結果となる。
    • OR条件で左辺がtrueであるため、右辺は評価されない。./d1/d2/d3は出力されない。

なお、他の条件があるなら以下のようにすれば良い。

find -path 除外するパス -prune -o 他の条件 -print

位置オプションとグローバルオプション

式の中にはfindコマンド自体や他の式の挙動を変更するものがある。これらは指定する位置により影響範囲が異なる位置オプションと、どこで指定されても全体に影響するグローバルオプションがある。見やすさの観点から以下のようにすると良い。

find [グローバルオプション] [検索開始場所] 式(位置オプションを含む)...

主なオプションを示す。

オプション名説明種類
-daystart時刻の比較を行うときに、今日の午前0時を基準にする。位置オプション
-regextype使用する正規表現のタイプを指定する。位置オプション
-depthディレクトリの内容を調べた後でディレクトリ自体を調べる。グローバルオプション
-maxdepth検索の深さの最大値を指定する。グローバルオプション
-mindepth検索の深さの最小値を指定する。グローバルオプション
-mount他のファイルシステムを跨がないようにする。グローバルオプション

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です