Linux

指定した条件にマッチするファイルを検索する find コマンド

投稿日:2018年12月6日 更新日:

find コマンドについて説明します。

※ 本ページで扱うのは、find (GNU findutils) 4.7.0-git です。

1. find コマンドの使い方

find コマンドの基本的な使い方は以下のように使います。

$ find パス 

動作としては、「パス」で指定したディレクトリ以下(再帰的に検索します)から、「」で指定した条件にマッチするファイル・ディレクトリを検索します。

式 (EXPRESSION)

は以下のパートに分けることができ、単に検索する以上のことができるのが find コマンドのすごいところです。

= 判別式 + アクション + グローバルオプション + ポジショナルオプション + 演算子

主なグローバルオプション、判別式、アクションを表にしました。

man ページの説明と独自の説明を合わせて追加してあります。

※ ポジショナルオプションはあまり使わないので省略しました。

主なグローバルオプション (GLOBAL OPTIONS)
オプション 説明
-maxdepth levelsコマンドライン引き数として指定したパスから最大 levels 段階下の ディレクトリまで探索する (levels は非負の整数)。
-depthディレクトリそのものより先に、ディレクトリの中身を処理する。
主な判別式 (TESTS)
判別式説明
-name pattern
  • ファイル名やディレクトリ名が、pattern に一致するなら真。
  • ファイル名のマッチングは、 fnmatch(3) ライブラリ関数を用いて行われる。
  • メタ文字 (‘*’, ‘?’, ‘[]’) は、 ベースネームの先頭にある `.’ とマッチする
  • あるディレクトリとそれ以下にあるファイルをまとめて無視するには、 -prune を使うとよい。
  • ‘*’などがシェルによって展開されてしまわないように、パターンは引用符で囲むこと。
-iname pattern-name と同じだが、大文字小文字を区別しない。
-path pattern
  • ファイル名がシェルのパターン pattern にマッチすれば真。
  • メタ文字は ‘/’ や ‘.’ を例外扱いしない。
-type c
  • ファイルのタイプが c であれば真。
  • c の位置には実際には 以下の文字が来る。
    • d : ディレクトリ
    • f : 通常のファイル
    • その他
-size ±n[cwbkMG]
  • ファイルが n 単位分の領域を使用していれば、真を返す (対象となるファイルのサイズを、単位にまで切り上げて比較する)。
  • + をつけると「より大きい」、- をつけると「より小さい」という意味になる。
  • 使える単位
    • ‘c’ 単位はバイト。
    • ‘w’ 単位はワード。1 ワードは 2 バイト。
    • ‘b’ 単位はブロック。1 ブロックは 512 バイト。(デフォルト)
    • ‘k’ 単位はキビバイト (1 キビバイトは 1024 バイト)。
    • ‘M’ 単位はメビバイト (1 メビバイトは 1048576 バイト)。
    • ‘G’ 単位はギビバイト (1 ギビバイトは 1073741824 バイト)。
-cmin n ファイルの最終ステータス変更日時が n 分前ならば真。
-mtime n ファイルの最終内容更新日時が n 日前ならば真。
-user uname ファイルの所有者が uname というユーザならば真 (ユーザ ID 番号で指定してもよい)。
-group gnameファイルの属するグループが gname ならば真 (グループ ID 番号で 指定してもよい)。
主なアクション (ACTIONS)
アクション 説明
-exec command ;
  • command を実行する。
  • command の返り値が 0 ならば、真を返す。
  • find のコマンドラインで指定されたこれ以降の引き数は、’;’ という引き数が現れるまで、 すべてコマンドに対する引き数と見なされる。
  • 文字列 ‘{}’ は、 それがコマンドの引き数中に現れるすべての場所で、現在処理中のファイル名に 置き換えられる。
-exec command {} +
  • 選択したファイルに対して指定したコマンドを実行するが、コマンドラインを形成するとき、選択した各ファイル名をコマンドラインの末尾に追加して行う。
  • コマンドラインが長くなりすぎるときは、 処理するファイル名の数を適切に分割して、コマンドを複数回実行する。
  • そのため、コマンドを呼び出す回数は、マッチしたファイルの数より少なくてすむ。
-ls
  • 真を返す。
  • 結果を詳細情報付きで表示する。
-print
  • 真を返す。
  • パス付きのファイル名を標準出力に表示し、各ファイル名の後ろに 改行文字を付ける。
-print0
  • 真を返す。
  • パス付きのファイル名を標準出力に表示し、各ファイル名の後ろにヌル文字を付加する。
  • find の出力を処理するプログラムが、改行文字を受け取ると問題が起きる場合に有用。
-prune
  • 真を返す。
  • ファイルがディレクトリの場合は、そのディレクトリ以下に降りて行かない。
  • 主に、-path と合わせて使う。
  • -depth が指定してあるときは、偽を返し、何もしない。

※ 式の中に -prune 以外のアクションが存在しない場合は、 式の結果が真になったすべてのファイルに対して -print が実行される。

主な演算子 (OPERATORS)
演算子説明
( expr )
  • カッコの内側を先に処理する。
  • Bashなどのシェルでは、\( expr \) と括弧をエスケープする必要がある。
! expr
  • expr が偽の場合、真になる。
expr1 expr2
  • 連続する二つの式は、and 結合と解釈される。
  • expr1 が偽の場合、expr2 は評価されない。
expr1 -a expr2
  • expr1 expr2 と同じ。
expr1 -o expr2
  • or 結合である。
  • expr1 が真ならば、expr2 は評価されない。

演算子を使い、複数の式を組み合わせることができます。

式の動作

  1. 式の要素は、演算子で区切られます。
  2. 与えられた式を左から右に向かって優先順位の高いものから評価します。但し、括弧内が先に処理されます。

以下のコマンドは何をしていることになるでしょうか?

$ find . -maxdepth 3 -type f \( -name '*.py' -o -name '*.c' \) -ls

※ シェルとして bash を使っています。

答えは以下です。

  1. カレントディレクトリに対し、
  2. 最大3階層下の ディレクトリまで探す。
  3. 種類は「ファイル」であり、
  4. 且つ(ファイル名が *.c もしくは *.h にマッチするファイル)
  5. その結果に対して、詳細表示を行う。

2. コマンド実行例

(1) 名前が ‘*.c’ にマッチするファイルを表示する。

$ find . -type f -name '*.c'
  • 「*.c」をクォートで囲むのを忘れないこと。

(2) 100分以内に更新したファイルを表示する。

$ find . -type f -cmin -100

(3) 100分以上前に更新したファイルを表示する。

$ find . -type f -cmin +100

(4) 10日以内に更新したファイルを表示する。

$ find . -type f -mtime -10

(5) 10日以上前に更新したファイルを表示する。

$ find . -type f -mtime +10

(6) カレントディレクトリ以下に存在するPNGファイルを、/tmp ディレクトリに移動する

$ find . -type f -name '*.png' -exec mv -t /tmp {} + 
  • mv コマンドの -t オプションは、移動先を指定している。
  • 1回の mv コマンド起動時に、なるべくたくさんのファイル名を渡してくれるので処理が速い。
  • -exec アクションで 末尾に “+” を付ける場合は、”{}”は引数の最後に置かなければいけない。

(7) xargs コマンドと組み合わせて使う場合

$ find . -print0 | xargs -0 grep hogehoge /dev/null
  • find 側では -print0 をセットし、xargs 側では -0 をセットする。
  • UNIX系のシステムでは、ファイル名として空白や改行を含むことができるが、xargs がこれを受け取った時、ファイル名の区切りだと認識してしまうのを防ぐため、ファイル名の区切り文字をヌル文字にする。
  • 最後に /dev/null を指定しているのは、grepコマンドによる出力の全ての行に、ファイル名を出力させるための小技です。(参照:コマンド:xargs: UNIX/Linuxの部屋

参照

📂-Linux

執筆者:labo


comment

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

関連記事

Linux

パターンにマッチした行を表示する grep コマンド

目次1. はじめに2. 主な使い方3. その他のオプション4. 正規表現について 1. はじめに grep は、対象ファイルの中で、指定した文字列パターンにマッチした行を表示するコマンドです。 ※ 本 …

Linux

umask によって適用されるパーミッションの確認ページを作成しました

Linux (や Mac) では、ファイルやディレクトリに「パーミッション」を設定することでアクセスを制限します。 パーミッションは、「所有者」「所有グループ」「その他」の3者に対して、 ファイルなら …

Let's Encrypt

Let’s Encrypt でワイルドカードを使う

手持ちの CentOS 7 に入れてある certbot パッケージが バージョン 0.22.0 になり、Let’s Encrypt のワイルドカードに対応しましたので試してみました。 目 …

Linux

シェルスクリプト (Bash) では組み込みコマンド set を活用しましょう

Linux や MacOS、Windows の WSL でシェルスクリプト(Bash)を書く場合は、組み込みコマンド set を活用しましょう。より完成度の高い処理を書くことができます。 スポンサード …

CentOS

CentOS 6 で yum update した時、remi-php70 レポジトリ内のパッケージの依存性解決ができない場合の解決方法

目次現象解決方法 その1解決方法 その2解決方法 その3まとめ参考 現象 remi-php70 リポジトリを使っている CentOS 6 の環境で PHP関連のパッケージを更新しようと思い、以下のコマ …