findコマンドでファイルを検索する方法

# この記事を書いたきっかけ
たくさんのファイルの中から目的のファイルを探したいときには、findコマンドを使うということを最近勉強しました。ただ、指定する方法について、いろいろな方法がありすぎて、一度勉強しただけでは整理しきれませんでした。ターミナルでコマンドを指定する方法を思い出せなくて、結局GUIの操作でファイルを探すということが何度かありました（検索窓は便利ですので）。


そこで、もっとfindコマンドを使いやすくしたい、もっとfindコマンドを理解したいと思い、記事を書きました。

実は、探したいファイルやディレクトリを、名前で指定するだけでなく、作成日時やファイルサイズなどの方法で指定することもできるみたいです。ですが、今回は日常的に使える簡単なオプションを中心にまとめました。

## findコマンドの使い方
findコマンドは、指定したディレクトリ内でファイルやディレクトリを検索するためのコマンドです。

コマンド：`find [オプション] ディレクトリ名 [検索パターン]`

findのあとにはディレクトリ名（起点となるパス名）が必要です。必要であれば、[オプション]や[検索パターン]を使用します。
***
findコマンドは引数で指定した「起点となるパス」「ディレクトリ」を起点に、その下のディレクトリを順にたどってファイルを検索します。ファイル名で検索したいときには「検索条件オプション」に「-name "ファイル名"」を指定します。
***
findコマンドとlsコマンドは、どちらもディレクトリ内のファイルやディレクトリを表示するために使用するので、似ていますが、違いがあります。

1. 階層的な検索
findはデフォルトで指定したディレクトリ内全体を検索しますが、lsはデフォルトでは当該ディレクトリのみを対象にリスト表示します（再帰的に表示するには-Rオプションが必要）。再起的とは、「階層的」「ネストされたディレクトリ全体」や「サブディレクトリを含む」という意味を持ちます。親ディレクトリ以下全てを検索するのがfindコマンドです。
2. 条件指定
findは多くの条件（名前、サイズ、更新日時など）で検索できますが、lsは基本的にリスト表示のみです。
3. 検索結果に対する操作
findは検索結果に対して他のコマンドを実行できます（-execオプションを使用した場合）。lsはリスト表示のみです。
## 目的別findコマンドの使い方
### 指定したディレクトリ内のディレクトリやファイルを検索したい
findコマンドを使って、特定のディレクトリ内でファイルを検索します。

コマンド：`find ディレクトリ名`
```
$ find example
example
example/file1.txt
example/file2.txt
example/subdir
example/subdir/file3.txt
```

### ファイル名を指定して検索したい（シェルによるパス名展開）
特定のファイル名を指定して検索する場合、シェルのワイルドカードを使用してファイル名を指定できます。この方法では、シェルがパス名を展開するため、サブディレクトリの内容が含まれる場合があります。
例：
コマンド：`find example/*.txt`

```
$ find example/*.txt
example/file1.txt
example/file2.txt
example/dir1.txt
example/dir1.txt/file3.txt
```
この形式では、シェルがexampleディレクトリ内の.txtファイルを展開し、それらのファイルをfindコマンドに渡します。結果として、サブディレクトリを検索しない場合もあります。
### ファイル名を指定してサブディレクトリも検索したい
-nameオプションを使うと、サブディレクトリも含めて検索できます。

コマンド：`find ディレクトリ名 -name "ファイル名"`
```
# exampleディレクトリ以下でファイル名が"*.txt"のファイルを検索したい

$ find example -name "*.txt"
example/file1.txt
example/file2.txt
example/subdir/file3.txt
```
### ファイルのみを検索したい
-type fオプションを使用すると、ファイルのみを検索できます。

コマンド：`find ディレクトリ名 -type f`
```
$ find example -type f
example/file1.txt
example/file2.txt
example/subdir/file3.txt
```
### ディレクトリのみを検索したい
-type dオプションを使用すると、ディレクトリのみを検索できます。

コマンド：`find ディレクトリ名 -type d`
```
$ find example -type d
example
example/subdir
```
### findコマンドでエラーメッセージが出た場合
検索開始パスに合致するファイルやディレクトリが存在しない場合、findコマンドはエラーメッセージを表示します。
```
# 例
$ find example/*.data
find: ‘example/*.data’: No such file or directory
```
一方、-nameオプションを使用した場合、存在しないファイルでもエラーメッセージは表示されません。

`find example -name "*.data"`
```
$ find example -name "*.data"
$
```

### 更新した日時で検索したい
-mtimeオプションを使用すると、指定した期間内に更新されたファイルを検索できます。以下の例では、24時間以内に更新されたファイルを検索します。

コマンド：`find example -name "ファイル名" -mtime 0`

```
$ find example -name "*.txt" -mtime 0
example/file1.txt
```
### ワイルドカードを使用してファイル名やディレクトリ名を指定して検索したい

シェルの機能であるワイルドカードを使用すると、複数の文字に合致するファイル名やディレクトリ名を指定できます。

**ワイルドカードの種類**
| 記号 | 意味 | 例 |
|:-:|:-|:-|
|  * | 0文字以上の任意の文字列  |*.txt|
| ?  |  任意の1文字 |hello?.txt|
|[]|角カッコ内の任意の文字。ハイフンで範囲を指定できる|[0-9], [a-zA-Z]|

```
# 現在のディレクトリ内で、任意の1文字を含むファイルを検索
$ find . -name "hello?.txt"
./hello1.txt
./helloA.txt

# 現在のディレクトリ内で、特定の文字範囲に一致するファイルを検索
$ find . -name "file[1-3].txt"
./file1.txt
./file2.txt
./file3.txt
```
# まとめ
「あのファイルってどこにあったっけ？」となったときは、それがカレントディレクトリ以下にあるとわかっている場合、`find . -name "ファイル名"`で実行すれば、パスを表示してくれることがわかりました。

他のオプションも面白そうなので、また記事にしてまとめたいと思います。