【図解:bash】 findコマンドの使い方(ファイル検索)

find は、指定したディレクトリの下にあるファイルやディレクトリを、名前や種類、サイズ、更新日時などの条件で探すコマンドです。この記事では、よく使うオプションを実際に実行し、結果を確かめながら使い方を整理します。

この記事でわかること
  1. find の基本の書き方(検索対象のパスと検索条件)
  2. 名前・種類・サイズ・更新日数で探すオプション(-name、-type、-size、-mtime)
  3. 条件の組み合わせ(AND、-or、-not)と括弧のエスケープ
  4. 見つかったファイルへのアクション(-print、-ls、-delete)

find の基本の書き方

find は、検索対象のパスのあとに検索条件を書きます。

find <検索対象のパス> <検索条件>

たとえば、/home/hirotano ディレクトリの下から、名前が data1 のファイルを探すには次のようにします。

hirotano@linux-1:~$ find /home/hirotano/ -name data1
/home/hirotano/data1
find/home/hirotano/-namedata1検索対象のパス(省略するとカレントディレクトリ)オプション(名前で検索)検索する値検索条件
図1 find コマンドの構文

検索対象のパスの下にあるサブディレクトリも、すべて検索します。検索条件には、ファイルの名前や種類、サイズ、更新日時など、さまざまなオプションを指定できます。

この記事では、ホームディレクトリ(カレントディレクトリ)にある次のファイルとディレクトリを検索の対象にします。

hirotano@linux-1:~$ ls -la
合計 1034312
drwxr-xr-x 8 hirotano hirotano       4096 12月 25 04:33 .
drwxr-xr-x 3 root     root           4096  7月 31 06:45 ..
-rw------- 1 hirotano hirotano       7189 12月 25 05:29 .bash_history
-rw-r--r-- 1 hirotano hirotano        220  2月 25  2020 .bash_logout
-rw-r--r-- 1 hirotano hirotano       3771  2月 25  2020 .bashrc
drwx------ 2 hirotano hirotano       4096  7月 31 06:49 .cache
drwx------ 3 hirotano hirotano       4096 12月 11 02:15 .config
-rw------- 1 hirotano hirotano         69 12月 24 14:31 .lesshst
drwxrwxr-x 3 hirotano hirotano       4096 12月 18 08:19 .local
-rw-r--r-- 1 hirotano hirotano        807  2月 25  2020 .profile
drwx------ 2 hirotano hirotano       4096  7月 31 08:42 .ssh
-rw-r--r-- 1 hirotano hirotano          0  7月 31 06:49 .sudo_as_admin_successful
-rw------- 1 hirotano hirotano       8860 12月 11 11:14 .viminfo
-rw-rw-r-- 1 hirotano hirotano          0 12月 19 12:00 1-music
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:17 11-music
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:17 2-music
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:05 Backup111
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:05 Backup222
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:05 Backup333
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:06 IMAGE
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:05 IMAGE1
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:06 IMAGE12
-rw-rw-r-- 1 hirotano hirotano   10485760 12月 25 01:42 data1
-rw-rw-r-- 1 hirotano hirotano 1048576000 12月 25 03:51 data11
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:04 data111
drwxrwxr-x 2 hirotano hirotano       4096 12月 24 08:50 dir1
drwxrwxr-x 2 hirotano hirotano       4096 12月 24 06:03 dir11
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:04 file1
-rw-rw-r-- 1 hirotano hirotano          0 12月 24 06:04 file2.txt

名前で検索(-name)

上の例のように、-name のあとに探したい名前を指定します。-name が比べるのは、パスからディレクトリの部分を除いたファイル名です。大文字と小文字を区別しないで探したいときは -iname を使います。

「ある文字列で始まる」のような条件は、ワイルドカード(* や ?)で指定します。ワイルドカードの意味は、次の記事を参考にしてください。

ワイルドカードは引用符で囲む

たとえば、カレントディレクトリ(.)の下から、名前が d で始まるものを探す場合は次のようにします。ワイルドカードを使うときは、パターンを引用符(ここではシングルクォート)で囲みます。

hirotano@linux-1:~$ find . -name 'd*'     
./dir11
./data11
./data111
./dir1
./data1
入力したコマンドfind に渡る引数find . -name 'd*'find . -name d*引用符で囲む:d* のまま find に渡るfind . -name d*find . -name data1 data11 data111 dir1 dir11先にパス名展開される:引数が多すぎてエラーfind . -name d\*find . -name d*\ でエスケープ:d* のまま find に渡る
図2 引用符の有無で find に渡る引数が変わる

引用符がないと、find が動く前に bash がパス名展開をします。カレントディレクトリに d で始まるファイルがあると、d* は data1 data11 data111 dir1 dir11 に置き換わり、find は -name のあとに名前が並んだ形で実行されるので、エラーになります。find には、展開する前の d* のまま渡す必要があります。

補足

引用符なしでも、たまたま動いてしまうことがあります。カレントディレクトリに一致するファイルが1つだけならその名前に置き換わってエラーにならず、一致するファイルがなければ d* がそのまま渡ります。どちらも意図した検索になるとは限らないので、ワイルドカードはいつも引用符で囲みます。

* の前にバックスラッシュを入れて、パス名展開をエスケープすることもできます。

hirotano@linux-1:~$ find . -name d\*
./dir11
./data11
./data111
./dir1
./data1

ファイルタイプで検索(-type)

ファイルかディレクトリかを条件にするには、-type を使います。通常のファイルは f、ディレクトリは d、シンボリックリンクは l を指定します。

find.-typedオプションd ディレクトリf 通常のファイルl シンボリックリンク
図3 -type の指定

次は、カレントディレクトリの下のディレクトリを探した例です。カレントディレクトリ自身(.)もディレクトリなので、結果に含まれます。

hirotano@linux-1:~$ find . -type d
.
./.local
./.local/share
./.local/share/nano
./dir11
./.ssh
./dir1
./.config
./.config/procps
./.cache

ファイルサイズで検索(-size)

ファイルのサイズを条件にするには、-size を使います。カレントディレクトリの下から 5M バイトを超えるファイルを探すには、-size のあとに +5M と指定します。

hirotano@linux-1:~$ find . -size +5M 
./data11
./data1
find.-size+5Mオプション+ より大きい- より小さいなし ちょうど単位c バイト k KiBM MiB G GiB省略時は 512 バイトのブロック
図4 -size の指定

数字の前の + は「より大きい」、- は「より小さい」を表し、どちらも付けなければ「ちょうど」を表します。単位は M(MiB)のほかに、c(バイト)、k(KiB、小文字)、G(GiB)が使えます。単位を省くと、512 バイトのブロック単位になります。

結果を見ると、10485760 バイト(10MiB)の data1 と、1048576000 バイト(1000MiB)の data11 が見つかっています。

注意

サイズは指定した単位に切り上げてから比べます。そのため -size -1M は「1MiB 未満」ではなく、サイズ 0 のファイルにしか一致しません。小さいサイズを細かく指定したいときは、-size -1048576c のようにバイト(c)で指定します。

更新日数で検索(-mtime)

ファイルの中身が最後に更新されてからの日数を条件にするには、-mtime を使います。日数は 24 時間を1日として数え、端数は切り捨てます。

カレントディレクトリの下から、5日前に更新されたファイルを探すには、-mtime のあとに 5 を指定します。この 5 は、更新から 5×24 時間以上、6×24 時間未満のものを指します。

hirotano@linux-1:~$ find . -mtime 5
./1-music

5日前より新しいもの(5×24 時間たっていないもの)は -5、もっと古いものは +5 と指定します。+5 は、端数を切り捨てた日数が 5 より大きいもの、つまり 6×24 時間以上前に更新されたものです。

今1日2日3日4日5日6日7日8日-mtime -55×24時間より新しい5-mtime 5-mtime +56×24時間以上前更新からの経過時間を 24 時間単位で数え、端数は切り捨てる-mtime 5 は「5×24 時間以上、6×24 時間未満」に更新されたもの
図5 -mtime の範囲

次は、5日前より新しいファイルを探した例です。

hirotano@linux-1:~$ find . -mtime -5
.
./.bash_history
./dir11
./2-music
./11-music
./IMAGE12
./Backup111
./data11
./.lesshst
./IMAGE1
./file2.txt
./data111
./dir1
./file1
./Backup333
./IMAGE
./data1
./Backup222

複数の条件を指定

検索条件は、いくつでも並べられます。並べた条件は AND(すべてを満たすもの)として扱われます。たとえば、5日前に更新され、かつ名前が music で終わるファイルを探すには次のようにします。

hirotano@linux-1:~$ find . -name '*music' -mtime 5
./1-music
find.-name'*music'-mtime5条件1:名前が music で終わる条件2:5日前に更新条件を並べると AND(すべての条件を満たすもの)になる
図6 条件を並べると AND になる

OR と NOT

条件どうしの関係は、論理演算子で指定することもできます。OR は -or、AND は -and と書きます(-o、-a と書いても同じです)。

\( 検索条件1 \) -or \( 検索条件2 \)

たとえば、名前が data で始まるもの、または5日前に更新されたものを探すには次のようにします。

hirotano@linux-1:~$ find . \( -name 'data*' \) -or \( -mtime 5 \)       
./data11
./1-music
./data111
./data1
find.\(-name'data*'\)-or\(-mtime5\)括弧は \ でエスケープ('(‘ のように引用符でもよい)どちらかを満たす括弧の前後にはスペースを入れる
図7 -or と括弧のエスケープ

括弧(( と ))は bash では特別な意味を持つ文字なので、バックスラッシュでエスケープします。また、括弧と条件の間にはスペースを入れます。

条件の前に -not を付けると、その条件を満たさないものを探せます。次は、名前が music で終わり、かつ5日前に更新されていないファイルを探した例です(最後の \) は次の行に表示されています)。

hirotano@linux-1:~$ find . \( -name '*music' \) -and \( -not -mtime 5 
\)
./2-music
./11-music
find.\(-name'*music'\)-and\(-not-mtime5\)名前が music で終わるかつ更新が5日前ではない-not は直後の条件を否定する(! と書いても同じ)
図8 -and と -not
補足

括弧を使わない場合、-and は -or より先に評価されます。AND と OR を混ぜるときは、意図した順に評価されるよう括弧で囲みます。

アクション

find には、見つかったファイルに対して何かをする「アクション」のオプションがあります。アクションを指定しない場合は、見つかったものを表示する -print が実行されます。-print を付けて実行すると、付けない場合と同じ結果になります。

hirotano@linux-1:~$ find . -name 'd*' -print
./dir11
./data11
./data111
./dir1
./data1
find.-name'd*'-ls検索条件-print結果を表示(省略時の動作)-lsls -dils の形式で表示-delete見つかったものを削除
図9 アクションの指定

-ls を付けると、ls -dils の形式で表示されます。更新日時やサイズ、パーミッションをまとめて確かめたいときに使います。

hirotano@linux-1:~$ find . -name 'd*' -ls
   524312      4 drwxrwxr-x   2 hirotano hirotano     4096 12月 24 06:03 ./dir11
   393253 1024004 -rw-rw-r--   1 hirotano hirotano 1048576000 12月 25 03:51 ./data11
   393254       0 -rw-rw-r--   1 hirotano hirotano          0 12月 24 06:04 ./data111
   524311       4 drwxrwxr-x   2 hirotano hirotano       4096 12月 24 08:50 ./dir1
   393252   10240 -rw-rw-r--   1 hirotano hirotano   10485760 12月 25 01:42 ./data1
列(data11 の行)意味
393253inode 番号
1024004使っているブロック数(1KiB 単位)
-rw-rw-r–ファイルの種類とパーミッション
1ハードリンクの数
hirotano hirotano所有者とグループ
1048576000サイズ(バイト)
12月 25 03:51最終更新日時
./data11パス

-delete を付けると、見つかったものを削除します。次の例では、d で始まるファイルと、空のディレクトリ dir1、dir11 が削除され、もう一度探しても何も見つかりません。

hirotano@linux-1:~$ find . -name 'd*' -delete
hirotano@linux-1:~$ find . -name 'd*'
hirotano@linux-1:~$
-delete の注意
  • -delete は確認なしで削除します。先に同じ条件で -print(またはアクションなし)を実行して、対象を確かめてから実行します。
  • find は、コマンドラインを左から順に式として評価します。-delete を条件より前に書くと、条件で絞り込む前にすべてを削除しようとするので、-delete は必ず最後に書きます。
  • ディレクトリは、空のときだけ削除できます。中身が残っているディレクトリの削除は失敗します。

まとめ

書き方意味
-name ‘d*’名前が d で始まる(ワイルドカードは引用符で囲む)
-type f / d / l通常のファイル/ディレクトリ/シンボリックリンク
-size +5M5MiB より大きい(- はより小さい、符号なしはちょうど)
-mtime 55×24 時間以上、6×24 時間未満に更新
-mtime -5 / +55×24 時間より新しい/6×24 時間以上前
条件1 条件2AND(-and、-a と同じ)
\( 条件1 \) -or \( 条件2 \)OR。括弧はエスケープして前後にスペース
-not 条件条件を満たさない
-print / -ls / -delete表示(省略時)/ls -dils 形式で表示/削除

コメント