ディレクトリの中を再帰的にたどってファイルを検索してきてくれるコマンド。タイムスタンプやファイルサイズ、ファイル名など、さまざまな条件で検索でき、検索条件はオプションで指定する。検索結果を出力するだけでなく、他のコマンドに引数として渡すこともできる。
検索対象となるディレクトリ、検索条件、アクションの順にコマンドライン引数で
$ find ディレクトリ 検索条件 アクション
というように指定する。
ディレクトリを省略すると、カレントディレクトリが対象になる。
検索条件を省略すると、すべてのファイル・ディレクトリがマッチするようになる。検索はファイルだけでなくディレクトリも対象である。
アクションを省略すると、-ls
アクションの扱いになり、単純に見つかったファイル・ディレクトリのパスが改行区切りで出力される。
従って、引数なしでfind
とすると、カレントディレクトリに含まれるすべてのファイル・ディレクトリを、ディレクトリを再帰的にたどりながら表示してくれる。
ファイル名などでのソートはしてくれないので、必要であればパイプでsort
コマンドをつなぐ必要がある。
アクションは単に検索結果を表示するだけの-ls
のほかに、他のコマンドを実行する-exec
などがある。-exec
は非常によく使うアクションである。->検索結果を元に他のコマンドを実行する方法
-name
パターン?
,*
,[...]
が使える。-empty
-type f
-type d
-perm
-perm -u=w
とする。-perm -u=r
-perm -u=w
-perm -u=x
検索条件は複数の条件を組み合わせることができ、単に複数の条件を羅列した場合にはそれらの条件がすべて成立するファイルのみが抽出される。その他に以下の演算子もある。
-a
条件-o
条件!
条件-ls
ls
コマンドの-gids
オプションと似たような書式で検索結果を表示する。-print
-print0
-printf
書式-exec
コマンド\;
\;
のバックスラッシュはシェルに対して;
をシェルの特殊文字であるコマンドの境界とみなされないようにするためのエスケープなので、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
のコマンドに渡す引数の最大数を制御するには
ls
コマンドのようにファイル名でのソートはしてくれないので、sort
コマンドを併用する必要がある。
$ find . -name ... | sort
YYYY-MM-DD hh:mm:ss
のフォーマットで表示するには2013/11/12アクション-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
というファイルにコピーするには2013/04/16$ find . -name ".ht*" | awk '{print "cp " $1 " " $1 ".example"}' | sh
$ find . -type l -exec ls -l {} \;
Permission denied
を表示しないようにするには2014/05/15find
で/
などを検索すると、Permission denied
というエラーメッセージが大量に出力されてしまう。このメッセージが邪魔なので抑制するには、以下のように単に標準エラー出力を捨てればよい。
$ find / ... 2>/dev/null
-mount
を使う。
$ find / -mount -name "hoge" 2>/dev/null
これは、hoge
という名前のファイルをルートからたどって探す。ただし別のファイルシステムにはたどらない。
## UIDが1000のユーザのホームディレクトリ$ find /home -maxdepth 1 -uid 1000
ただし、これはホームディレクトリが/home
直下にあることを決め打ちしている。
$ find . -type d -empty
$ find . -type f -empty
検索条件として-perm -u=x -type f
を付ける。-perm -u=x
で実行権限のあるファイルを条件にするのだが、これだとディレクトリにもマッチしてしまう。
ディレクトリに対する実行権限というのは、ディレクトリが本当に実行可能というわけではなく、そのディレクトリの中にcd
できる、という意味なので、本当に実行可能なファイルを検索するには、-type f
を付けてディレクトリを除外しないといけない。
例
$ find . -perm -u=x -type f
find
またはls -aR
にgrep
を組み合わせるのがいいかも。
$ 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