ファイルを検索したい(find)

$ find [検索パス] [検索条件]

// シンボリックリンクを追跡
$ find -L [検索パス] [検索条件]

// 文字列を安全に検索(macOS/BSD版)
$ find -X [検索パス] [検索条件]

// 正規表現で検索(macOS/BSD版)
$ find -E [検索パス] [検索条件]

findコマンドで、ファイルやディレクトリを検索できます。 [検索パス]と[検索条件]を指定することで、任意の条件でファイルを抽出できます。 検索パス名の末尾の/ (trailing-slash)は不要です。

-Lオプションで、シンボリックリンクを追跡して検索できます。 -Xオプションで、文字列を安全に検索できます。 検索結果をxargsに渡すときに便利です。

-Eオプションで、正規表現を使った検索ができます。 ただし、これはmacOS/BSD版のfindコマンドでのみ使えるオプションです。

findはUnix初期からあるコマンドのひとつです。 そのため、最近のコマンドオプションのような -ショートオプション、 --ロングオプションのような区別がありません。

拡張子で探したい(-name)

// HTMLファイルを探したい
$ find 検索パス -name "*.html"

// ZIPファイルを探したい
$ find 検索パス -name "*.zip"

// HTML以外のファイルを探したい
$ find 検索パス ! -name "*.html"

// 大文字/小文字を区別せずにHTMLファイルを探したい
$ find 検索パス -iname "*.HTML"

// JPEGまたはPNGファイルを探したい
$ find 検索パス \( -name "*.jpg" -o -name "*.png" \)

-nameオプションで、検索するファイル名のパターンを指定できます。

*.htmlのようなglobパターンで、拡張子に合わせて検索できます。 NOT検索する場合は!を、 大文字/小文字を区別せずに検索したい場合は-inameを使います。

OR検索する場合は-oを使います。 -oを使うときは、-name同士が独立した条件として評価されないように \( ... \)でグループ化する必要があります。

同じ条件は-regex ".*\.\(jpg\|png\)$"でも書けますが、-regexはファイル名ではなく検索パス全体にマッチする点に注意してください。

ファイルの種類で探したい(-type)

// ファイルを探したい
$ find 検索パス -type f

// ディレクトリを探したい
$ find 検索パス -type d

// シンボリックリンクを探したい
$ find 検索パス -type l

// 空のディレクトリを探したい
$ find 検索パス -type d -empty

// 実行可能なファイルを探したい
$ find 検索パス -type f -perm -u+x

// リンク切れのシンボリックリンクを探したい
$ find 検索パス -xtype l

-typeオプションで、検索するファイルの種類を指定できます。 ファイル(f)、ディレクトリ(d)、シンボリックリンク(l)などを選択できます。 -emptyオプションと組み合わせて、空のファイル、空のディレクトリを検索できます。 -permオプションと組み合わせて、実行権限を持つファイルだけに絞り込めます。

-xtypeは-typeのシンボリックリンク版で、リンクの参照先を評価します。 リンク先が存在しない(壊れた)シンボリックリンクを探すのに便利です。

タイムスタンプで探したい(-ctime / -mtime / -atime)

// ステータス変更が7日以上前
$ find 検索パス -ctime +7

// 最終更新日が28日以内
$ find 検索パス -mtime -28

// 10分以上前 - 60分以内に変更したファイルを探したい
$ find 検索パス -mmin +10 -mmin -60

// 数分以内にステータス変更されたファイルを探したい
$ find 検索パス -cmin -10

-*time系のオプションで、ファイルのタイムスタンプを使って検索できます。 -mtimeは最終更新日、 -atimeは最終アクセス日、 -ctimeはステータス変更日を基準に検索できます。

基準は現在時刻で、 -NはN日以内、 +NはN日以上前にマッチします。

-*min系のオプションを使うと、日単位ではなく分単位で指定できます。

サイズで探したい(-size)

// 100kB以上のファイルを探したい
$ find 検索パス -size +100k

// 10MB以上のファイルを探したい
$ find 検索パス -size +10M

// 10MB - 50MBのファイルを探したい
$ find 検索パス -size +10M -size -50M

-sizeオプションでファイルサイズを基準に検索できます。 -サイズはサイズ以下、 +サイズはサイズ以上にマッチします。 重たいファイルの削除を検討したい場合に重宝します。

深さを指定したい(-maxdepth)

// 2階層目まで探したい
$ find 検索パス -maxdepth 2 -name "*.html"

// 4階層目まで探したい
$ find 検索パス -maxdepth 4 -name "*.html"

-maxdepthオプションで検索する階層の深さを指定できます。

正規表現で探したい(-regex)

$ find 検索パス -regex 正規表現

-regexオプションで、ファイル名ではなくパス全体を正規表現で検索できます。 -nameのglobパターンより複雑な条件を指定したいときに使います。

検索結果の出力形式を変えたい(-ls / -print0)

// 検索結果を ls -l 形式で表示
$ find 検索パス -ls

// 検索結果をヌル文字(\0)区切りで表示
$ find 検索パス -print0

-lsで、検索結果をls -lと同じ形式で表示できます。 パーミッションやサイズなどを確認したいときに便利です。

-print0で区切り文字を改行(\n / 0x0A / U+000A)からヌル文字(\0 / 0x00 / U+0000)に変更できます。 このオプションは、xargsの--null(-0)オプションと組み合わせて使うことが多いです。

ヒント

-print0は、ファイル名が空白文字を含むなど、検索結果に半角スペース(0x20 / U+0020)が含まれている場合に効果的です。 xargsは、引数を受け取るときに、改行と空白文字で区切ってしまいます。 そのため、空白文字を含むファイル名があると、そこで引数が分割されてしまい、意図しない動作となります。 find -print0でヌル文字区切りにすること、 そしてで、xargs --nullでヌル文字を区切りとして受け取ることで、空白文字を含むファイル名でも正しく処理できるようになります。

グループ名で探したい(-group)

$ find 検索パス -group グループ名

所有者不明のファイルを探したい(-nouser)

# 所有者不明のHTMLファイルを探したい
$ find 検索パス -type f -nouser -name "*.html"

# グループ不明のHTMLファイルを探したい
$ find 検索パス -type f -nogroup -name "*.html"

空のディレクトリを削除したい(-empty -delete)

$ find 検索パス -type d -empty -delete

-emptyオプションを使って、空のディレクトリが検索できます。 -deleteオプションを追加して、一括削除できます。

パイプ処理したい

$ find 検索パス 検索条件 -print0 | xargs -0 コマンド
$ find -X 検索パス 検索条件 | xargs コマンド

検索した結果をパイプして、さらにテキスト処理できます。 そのときxargsに渡すことで、検索結果を任意のコマンドの引数として利用できます。

-print0オプションについては、前述の「検索結果の出力形式を変えたい」を参照してください。

GFSローテーションしたい

 1#!/bin/bash
 2
 3# 日次:毎日;7回分を保存
 4# 週次:毎週日曜日;4回分を保存
 5
 6SOURCE_DIR="バックアップしたいディレクトリ"
 7BACKUP_DIR="バックアップを保存するディレクトリ"
 8
 9# バックアップ日時:ファイル名に追加
10DATE=$(date +%Y%m%d)
11
12# 日次バックアップ
13tar zcvf ${BACKUP_DIR}/daily/${DATE}_backup_daily.tar.gz ${SOURCE_DIR}
14find ${BACKUP_DIR}/daily/ -type f -mtime +7 -print0 | xargs -0 rm
15
16# 週次バックアップ
17if [[ $(date +%u) -eq 7 ]]; then
18    tar zcvf ${BACKUP_DIR}/weekly/${DATE}_backup_weekly.tar.gz ${SOURCE_DIR}
19    find ${BACKUP_DIR}/weekly/ -type f -mtime +28 -print0 | xargs -0 rm
20fi

-mtimeオプションを活用すると 日次・週次・月次バックアップを取得するときにローテーションが組めます。 このようなローテーションを GFS(Grandfather-Father-Son)ローテーションと 呼ぶそうです。