find コマンド

ディレクトリの中を再帰的にたどってファイルを検索してきてくれるコマンド。タイムスタンプやファイルサイズ、ファイル名など、さまざまな条件で検索でき、検索条件はオプションで指定する。検索結果を出力するだけでなく、他のコマンドに引数として渡すこともできる。

基本的な使い方

検索対象となるディレクトリ、検索条件、アクションの順にコマンドライン引数で

$ find ディレクトリ 検索条件 アクション

というように指定する。

ディレクトリを省略すると、カレントディレクトリが対象になる。

検索条件を省略すると、すべてのファイル・ディレクトリがマッチするようになる。検索はファイルだけでなくディレクトリも対象である。

アクションを省略すると、-lsアクションの扱いになり、単純に見つかったファイル・ディレクトリのパスが改行区切りで出力される。

従って、引数なしで find とすると、カレントディレクトリに含まれるすべてのファイル・ディレクトリを、ディレクトリを再帰的にたどりながら表示してくれる。

ファイル名などでのソートはしてくれないので、必要であればパイプでsortコマンドをつなぐ必要がある。

アクションは単に検索結果を表示するだけの-lsのほかに、他のコマンドを実行する-execなどがある。 -execは非常によく使うアクションである。-> 検索結果を元に他のコマンドを実行する方法

スポンサーリンク

検索条件

-name パターン
ファイル名がパターンにマッチするファイル。パターンは正規表現ではなく、 シェルで使えるワイルドカードに似ていて、?, *, [...] が使える。
-empty
空のファイル。ディレクトリの場合は中身に要素が1つもない場合に空とみなされる。
-type f
ディレクトリではなくファイル。
-type d
通常のファイルではなくディレクトリ。
-perm
後ろにパラメータを付けて、パーミッションを条件判定する。 ユーザに対する書き込み権限があるファイルを探すには -perm -u=w とする。
-perm -u=r
ユーザに対する読み込み権限があるファイル。
-perm -u=w
ユーザに対する書き込み権限があるファイル。
-perm -u=x
ユーザに対する実行権限があるファイル。ディレクトリにもマッチすることに注意。

検索条件は複数の条件を組み合わせることができ、単に複数の条件を羅列した場合にはそれらの条件がすべて成立するファイルのみが抽出される。その他に以下の演算子もある。

条件 -a 条件
論理積。単に複数の条件を並べるのと同じ。
条件 -o 条件
論理和。どちらかの条件が成立すればよい。
! 条件
否定

アクション

-ls
lsコマンド-gids オプションと似たような書式で検索結果を表示する。
-print
ファイルのパスを改行区切りで表示する。このアクションがデフォルト。
-print0
ファイルのパスをNULL文字区切りで表示する。
-printf 書式
書式に基づいてファイルのパスを表示する。パスだけでなく、タイムスタンプやファイルサイズも表示できる。
-exec コマンド \;
オプションの後に指定するコマンドを検索結果1つずつに対して実行する。 最後の \; のバックスラッシュはシェルに対して ; をシェルの特殊文字である コマンドの境界とみなされないようにするための エスケープなので、findコマンド自体には最後に ; だけを渡していることになる。 -> 検索結果を元に他のコマンドを実行する方法
-exec コマンド +
-exec の最後の \;+ にすると、オプションの後に指定するコマンドに検索結果をまとめて渡して実行する。
-ok コマンド \;
-exec とよく似ているがコマンド実行前に都度確認を求めてくれる。

検索結果を元に他のコマンドを実行する方法

findコマンドでの検索結果を他のコマンドに渡して、コマンドに大量のファイルを処理させるにはいくつか方法があるが、まずは-execアクションを使う方法。

$ find . -type f -exec chmod 600 {} \;

これは検索結果のファイル(-type f なのでディレクトリ以外のファイルすべて)に対してパーミッションを600にするもの。

-exec のあとに任意のコマンドを書いて、検索結果のファイルパスが入ってほしい場所に {} と書いて、最後に \; と書く。こうすると chmod 600 foo.txt みたいなコマンドがファイルの数だけ実行される。

ただ、この方法だとファイルの数だけコマンドが起動してしまうので、実行する内容によってはとても効率が悪い。 chmodみたいに複数のファイル名をパラメータで渡せばまとめて処理してくれるコマンドも多いので、そういうコマンドを使う場合は、以下のようにする。

$ find . -type f -exec chmod 600 {} +

\; の代わりに + と書くと、ファイルパスをまとめてパラメータに渡してくれるので、 chmod 600 foo.txt bar.txt baz.txt のようなイメージでコマンドが実行される。ファイルごとにコマンドを起動するオーバーヘッドがなくなるので、処理速度は速くなる。

ただ、理由はよくわからないが + を使うよりもxargsコマンドを使うケースが多い気がする。 xargsでは以下のようにパイプでつなぐ。

$ find . -type f | xargs chmod 600

こうするとxargsコマンドは chmod 600 foo.txt bar.txt baz.txt のように複数のファイルを纏めてパラメータに入れて、コマンドを起動する。

xargsを使うとfindの結果が100個あったら次のコマンドに100個のパラメータが渡されるが、 20個ずつに分割して5回コマンドを実行する、という制御も可能である。 -> xargsのコマンドに渡す引数の最大数を制御するには

HOWTO

ファイル名順に並べて表示するには

lsコマンドのようにファイル名でのソートはしてくれないので、 sortコマンドを併用する必要がある。

$ find . -name ... | sort

タイムスタンプを YYYY-MM-DD hh:mm:ss のフォーマットで表示するには

アクション -printf でファイル一覧を表示するときのフォーマットを指定する。

$ find . -printf "%M %n %u %g %k %TY-%Tm-%Td %TH:%TM:%TS %p\n"

タイムスタンプの新しい順にファイル一覧を表示するには

アクション -printf でファイル一覧とともにタイムスタンプを出力して、 sortコマンドで並び替えをする。

$ find . -printf "%M %n %u %g %k %TY-%Tm-%Td %TH:%TM:%TS %p\n" | sort -r -k6,7

特定の日に更新したファイルの一覧を表示するには

例えば、24日前~23日前に更新したファイルの一覧を表示したい場合、

$ find / -mtime -24 -mtime +22 -ls | less

この場合、ちょうど24日前の現在時刻よりも最近で、 23日前の現在時刻よりも古い時間または23日前の現在時刻ちょうどに更新されたファイルをリスト表示する。”+22”とする必要あり。

カレントディレクトリ以下にある .ht で始まるファイルをそれぞれ .ht*.example というファイルにコピーするには

$ find . -name ".ht*" | awk '{print "cp " $1 " " $1 ".example"}' | sh

カレントディレクトリ以下にあるすべてのシンボリックリンクを探すには

$ find . -type l -exec ls -l {} \;

Permission denied を表示しないようにするには

find/ などを検索すると、 Permission denied というエラーメッセージが大量に出力されてしまう。このメッセージが邪魔なので抑制するには、以下のように単に標準エラー出力を捨てればよい。

$ find / ... 2>/dev/null

別のマウント領域の中は探索しないようにするには

-mount を使う。

$ find / -mount -name "hoge" 2>/dev/null

これは、hogeという名前のファイルをルートからたどって探す。ただし別のファイルシステムにはたどらない。

UIDからそのユーザのホームディレクトリを調べる簡単な方法

## UIDが1000のユーザのホームディレクトリ
$ find /home -maxdepth 1 -uid 1000

ただし、これはホームディレクトリが /home 直下にあることを決め打ちしている。

ディレクトリの中にあるたくさんのファイルの文字列を全置換する方法

ディレクトリの中を再帰的に全置換するには参照。

空のディレクトリの一覧を表示するには

$ find . -type d -empty

サイズ0のファイルの一覧を表示するには

$ find . -type f -empty

たくさんのファイルをまとめて less で閲覧するには

-> たくさんのファイルをまとめて less で閲覧するには

実行可能なファイルを検索するには

検索条件として -perm -u=x -type f を付ける。 -perm -u=x で実行権限のあるファイルを条件にするのだが、これだとディレクトリにもマッチしてしまう。

ディレクトリに対する実行権限というのは、ディレクトリが本当に実行可能というわけではなく、そのディレクトリの中にcdできる、という意味なので、本当に実行可能なファイルを検索するには、 -type f を付けてディレクトリを除外しないといけない。

$ find . -perm -u=x -type f

ファイル名を正規表現で検索するには

find または ls -aRgrep を組み合わせるのがいいかも。

$ find . | grep PATTERN
$ ls -aR | grep PATTERN

外部リンク

特定の日に更新したファイルの一覧を表示するコマンド
http://hydrocul.seesaa.net/article/134240824.html

最近更新したファイルの一覧を表示するコマンド
http://hydrocul.seesaa.net/article/119629133.html

ディレクトリの中にあるすべての .svn ディレクトリを消す方法
http://hydrocul.seesaa.net/article/126101968.html

ディレクトリの中にあるすべてのディレクトリ・ファイルのパーミッションを変更する方法
http://hydrocul.seesaa.net/article/124463048.html

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。
スポンサーリンク