ls, find, grepコマンドをきちんと理解する

ls、find、grep。
ファイル表示、ファイル検索に毎日使う基本的なコマンド達です。
毎日使ってはいても、これらのコマンドにはまだ自分が引き出せてない秘めた力がたくさんありそうだったので、一度腰を据えてmanページを読み込み、きちんと理解してみることにしました。
使用頻度が高いだけに、仲良くなればなるほど、日々の開発ライフ、運用ライフが豊かになるはず。
しっかり相手（コマンド）のことを理解し、最良の友となりましょう！
*検証環境：Ubuntu 18.04.3 LTS on EC2*

## 基本方針
* manページを全て読み、載っている全てのオプションを試す
* 調査した内容を基にコマンドの基本的な使用方法とオプションの全体像をまとめる
* 使用頻度が高そうなオプションは、実行例を含めて詳細を説明する
* それ以外でたまに使いそうなオプションは、概要を説明する
* オプションの使用頻度の判断は基本的に主観だが、自分の周りの人がよく使っていそうなものは漏らさないようにする

## コマンド解説① lsコマンド
```
$ whatis ls
ls (1)               - list directory contents
```
ディレクトリのファイルリストを表示するコマンド。
Linuxを使い始める人がまず最初に覚え、使用頻度も一番高いであろう愛すべきコマンド。
検証バージョンはこちら。

```
$ ls --version
ls (GNU coreutils) 8.28
```

### 基本的な使い方

いまさら説明するまでもありませんが、念のため。

```shell
# カレントディレクトリのファイルリストを表示
$ ls
hoge  piyo

# 指定したディレクトリのファイルリストを表示
$ ls /var/
backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp

# 詳細情報を表示
$ ls -l
total 8
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo

# ドットファイルを含めて表示
$ ls -a
.  ..  .bash_history  .bashrc  hoge  piyo
```

### 全体を俯瞰してみる

lsコマンドで指定できるオプションは、大きく3種類。

1. 表示対象指定
1. 表示方法（表示フォーマット）指定
1. 表示順指定

なのでコマンドを使う際には、下記の順で考えて使用するオプションを決めるのがよさそう。

**　どのディレクトリやファイルを表示対象としたいのか**
**　↓**
**　表示対象としたファイルについて、どのような情報を表示したいのか**
**　↓**
**　情報を表示する際に、リストをどの順序で表示したいのか**

ちなみに指定できるオプション数は全部で59個あります。
心が折れそうな数ですが、最良の友となるために全部試していきましょう。

|カテゴリ|オプション数|備考|
|:-:|:-:|:-:|
|表示対象指定|9||
|表示方法指定|37||
|表示順指定|11||
|その他|2|--helpと--version|

### 表示対象指定

まずは表示対象の指定から。
主に下記のようなことを指定可能。

* 表示対象とするディレクトリやファイル
* ドットファイルを表示するか
* リンクはリンク自体の情報を表示するか、それともリンク先の情報を表示するか
* サブディレクトリの中身も表示するか

```shell
# 表示対象とするディレクトリやファイルは引数で指定する（複数指定可能）
$ ls /usr/ /var/
/usr/:
bin  games  include  lib  local  sbin  share  src

/var/:
backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp

# -a ドットファイルを含めて表示する（.と..も含む）
$ ls -a
.  ..  .bash_history  .bashrc  hoge  piyo

# -A ドットファイルを含めて表示する（.と..は含まない）
$ ls -A
.bash_history  .bashrc  hoge  piyo

# -d ディレクトリの中身ではなく、ディレクトリ自体の情報を表示
$ ls -ld /usr/
drwxr-xr-x 10 root root 4096 Oct  2 17:08 /usr/

# -H リンク先の情報を表示する
## 説明のためにまずリンクを作成
$ ln -s /usr

## -Hを指定しない場合
$ ls -l usr
lrwxrwxrwx 1 ubuntu ubuntu 5 Dec 15 13:37 usr -> /usr
## リンク自体の情報を表示する

## -Hを指定した場合
$ ls -lH usr
total 48
drwxr-xr-x   2 root root 20480 Dec 14 13:41 bin
drwxr-xr-x   2 root root  4096 Apr 24  2018 games
drwxr-xr-x   4 root root  4096 Dec 14 13:40 include
・・・
## リンク先の情報を表示（ls -l usr/ でも可）

# -R サブディレクトリの中身も含めて表示する
$ ls -R /var/lib/dpkg
/var/lib/dpkg:
alternatives  cmethopt    diversions-old  lock           parts         status      triggers
available     diversions  info            lock-frontend  statoverride  status-old  updates

/var/lib/dpkg/alternatives:
awk            ex    infobrowser  jsonpointer  lzma  newt-palette  pinentry  rmt    rvim           traceroute6  vim      w
builtins.7.gz  from  jsondiff     jsonschema   mt    pager         rcp       rsh    telnet         vi           vimdiff  write
editor         ftp   jsonpatch    locate       nc    pico          rlogin    rview  text.plymouth  view         vtrgb

/var/lib/dpkg/info:
・・・

# -I GLOB 指定したファイル名に一致するファイルを非表示にする（ワイルドカードを使用可能）
## -Iを指定しない場合
$ ls /usr/
bin  games  include  lib  local  sbin  share  src

## -Iを指定した場合
$ ls -I *bin /usr/
games  include  lib  local  share  src
## binとsbinが非表示になった
```

<details><summary>表示対象指定関連の全オプション</summary><div>

```
       -a, --all
              do not ignore entries starting with .

       -A, --almost-all
              do not list implied . and ..

       -B, --ignore-backups
              do not list implied entries ending with ~

       -d, --directory
              list directories themselves, not their contents

       -H, --dereference-command-line
              follow symbolic links listed on the command line

       --hide=PATTERN
              do not list implied entries matching shell PATTERN (overridden by -a or -A)

       -I, --ignore=PATTERN
              do not list implied entries matching shell PATTERN

       -L, --dereference
              when showing file information for a symbolic link, show information for the file the link references rather  than  for  the
              link itself

       -R, --recursive
              list subdirectories recursively
```

</div></details>

`-B`バックアップファイルを表示しない、`-L`コマンドラインで指定したディレクトリ以外もリンク先の情報を表示する、なども指定可能。また`-I`に似たオプションとして`--hide`があるが、`-a`、`-A`と同時指定できないので`-I`のほうがおすすめ。

実用的には
`-A ドットファイルを含めて表示する（.と..は含まない）`
`-R サブディレクトリの中身も含めて表示する`
`-I GLOB 指定したファイル名に一致するファイルを非表示にする`
あたりを覚えておけばよさそう。

### 表示方法指定

lsコマンドの主要オプション群。
表示対象としたファイルを多彩なフォーマットで表示可能。
主に下記のようなことを指定可能。

* ファイルの種類を表示するか
* ファイルリストはカラムで表示するか、1ファイル1行で表示するか
* ファイルの詳細情報を表示するか
* 詳細情報表示時に表示する情報
* 詳細情報表示時のファイルサイズや日付のフォーマット

```shell
# -F ファイルの種類を記号で表示する
$ ls -F /lib/
apparmor/       ebtables/  klibc-wBFLvVtxy4xJqEadIBJMa78iJz8.so*  lsb/         modules-load.d/  recovery-mode/  udev/
console-setup/  hdparm/    libhandle.so.1@                        modprobe.d/  netplan/         systemd/        ufw/
cryptsetup/     init/      libhandle.so.1.0.3                     modules/     open-iscsi/      terminfo/       x86_64-linux-gnu/
## / ディレクトリ
## * 実行可能ファイル
## @ リンク

# -1 1ファイル1行で表示する
$ ls -1 /usr/
bin
games
include
lib
local
sbin
share
src

# -m ファイルリストをカンマ区切りで表示する
$ ls -m /usr/
bin, games, include, lib, local, sbin, share, src

# -C リダイレクトやパイプ時もカラムで表示する（通常の画面表示時と同様の表示）
## -Cを指定しない場合
$ ls > test.txt
$ cat test.txt
hoge
piyo
test.txt
## リダイレクトすると1ファイル1行となる

## -Cを指定した場合
$ ls -C > test.txt
$ cat test.txt
hoge  piyo  test.txt
## リダイレクトしてもカラム表示のままとなる

# -i ファイルのinodeを表示する
$ ls -i
268594 hoge  283029 piyo  256221 test.txt  256220 usr

# -l 詳細情報を表示する（ロングフォーマット表示）
$ ls -l
total 12
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo
-rw-rw-r-- 1 ubuntu ubuntu   23 Dec 16 14:50 test.txt
lrwxrwxrwx 1 ubuntu ubuntu    4 Dec 16 14:14 usr -> /usr
## ファイルリストの最初の一文字はd：ディレクトリ、l：リンク、-：ファイル
## その後はパーミッション、ハードリンク数、所有者、グループ、ファイルサイズ、更新日時、ファイル名が表示される
## 一番最初の行に表示されている「total 12」はブロックサイズの合計（サブディレクトリは含まない）

# -s ファイル毎のブロックサイズを表示する
$ ls -s
total 12
4 hoge  4 piyo  4 test.txt  0 usr
## 検証した環境だと1ブロック=1024バイトで表示された

# -g 所有者を表示しない（-lの指定がなくてもロングフォーマット表示になる）
# -o グループを表示しない（-lの指定がなくてもロングフォーマット表示になる）
$ ls -go
total 12
drwxrwxr-x 2 4096 Dec 14 14:26 hoge
drwxrwxr-x 2 4096 Dec 14 14:28 piyo
-rw-rw-r-- 1   23 Dec 16 15:03 test.txt
lrwxrwxrwx 1    4 Dec 16 14:14 usr -> /usr

# -h ファイルサイズを読みやすい単位で表示する（-lの指定が必要）
$ ls -lh /lib/
total 172K
drwxr-xr-x  2 root root 4.0K Oct  2 17:10 apparmor
drwxr-xr-x  2 root root 4.0K Oct  2 17:09 console-setup
drwxr-xr-x  4 root root 4.0K Oct  2 17:10 cryptsetup
drwxr-xr-x  2 root root 4.0K Oct  2 17:10 ebtables
drwxr-xr-x  2 root root 4.0K Oct  2 17:10 hdparm
drwxr-xr-x  2 root root 4.0K Oct  2 17:09 init
-rwxr-xr-x  1 root root  73K Nov  9  2017 klibc-wBFLvVtxy4xJqEadIBJMa78iJz8.so
lrwxrwxrwx  1 root root   18 Apr 18  2018 libhandle.so.1 -> libhandle.so.1.0.3
-rw-r--r--  1 root root  15K Apr 18  2018 libhandle.so.1.0.3
・・・

# --full-time 更新日時をナノ秒まで表示し、タイムゾーンも表示する（-lの指定は不要）
$ ls --full-time
total 12
drwxrwxr-x 2 ubuntu ubuntu 4096 2019-12-14 14:26:20.908303620 +0000 hoge
drwxrwxr-x 2 ubuntu ubuntu 4096 2019-12-14 14:28:04.972521167 +0000 piyo
-rw-rw-r-- 1 ubuntu ubuntu   23 2019-12-16 15:03:09.700972620 +0000 test.txt
lrwxrwxrwx 1 ubuntu ubuntu    4 2019-12-16 14:14:22.280880698 +0000 usr -> /usr
```

<details><summary>表示方法指定関連の全オプション</summary><div>

```
       --author
              with -l, print the author of each file

       -b, --escape
              print C-style escapes for nongraphic characters

       --block-size=SIZE
              scale sizes by SIZE before printing them; e.g., '--block-size=M' prints sizes in units of 1,048,576 bytes; see SIZE  format
              below

       -C     list entries by columns

       --color[=WHEN]
              colorize the output; WHEN can be 'always' (default if omitted), 'auto', or 'never'; more info below

       -D, --dired
              generate output designed for Emacs' dired mode

       -F, --classify
              append indicator (one of */=>@|) to entries

       --file-type
              likewise, except do not append '*'

       --format=WORD
              across -x, commas -m, horizontal -x, long -l, single-column -1, verbose -l, vertical -C

       --full-time
              like -l --time-style=full-iso

       -g     like -l, but do not list owner

       -G, --no-group
              in a long listing, don't print group names

       -h, --human-readable
              with -l and/or -s, print human readable sizes (e.g., 1K 234M 2G)

       --si   likewise, but use powers of 1000 not 1024

       --dereference-command-line-symlink-to-dir
              follow each command line symbolic link

              that points to a directory

       --hide=PATTERN
              do not list implied entries matching shell PATTERN (overridden by -a or -A)

       --hyperlink[=WHEN]
              hyperlink file names; WHEN can be 'always' (default if omitted), 'auto', or 'never'

       --indicator-style=WORD
              append indicator with style WORD to entry names: none (default), slash (-p), file-type (--file-type), classify (-F)

       -i, --inode
              print the index number of each file

       -I, --ignore=PATTERN
              do not list implied entries matching shell PATTERN

       -k, --kibibytes
              default to 1024-byte blocks for disk usage

       -l     use a long listing format

       -m     fill width with a comma separated list of entries

       -n, --numeric-uid-gid
              like -l, but list numeric user and group IDs

       -N, --literal
              print entry names without quoting

       -o     like -l, but do not list group information

       -p, --indicator-style=slash
              append / indicator to directories

       -q, --hide-control-chars
              print ? instead of nongraphic characters

       --show-control-chars
              show nongraphic characters as-is (the default, unless program is 'ls' and output is a terminal)

       -Q, --quote-name
              enclose entry names in double quotes

       --quoting-style=WORD
              use quoting style WORD for entry names: literal, locale, shell, shell-always, shell-escape, shell-escape-always, c, escape

       -s, --size
              print the allocated size of each file, in blocks

       --time=WORD
              with  -l,  show  time as WORD instead of default modification time: atime or access or use (-u); ctime or status (-c); also
              use specified time as sort key if --sort=time (newest first)

       --time-style=STYLE
              with -l, show times using style STYLE: full-iso, long-iso, iso, locale, or +FORMAT; FORMAT is interpreted like  in  'date';
              if  FORMAT  is  FORMAT1<newline>FORMAT2,  then FORMAT1 applies to non-recent files and FORMAT2 to recent files; if STYLE is
              prefixed with 'posix-', STYLE takes effect only outside the POSIX locale

       -T, --tabsize=COLS
              assume tab stops at each COLS instead of 8

       -w, --width=COLS
              set output width to COLS.  0 means no limit

       -x     list entries by lines instead of by columns

       -Z, --context
              print any security context of each file

       -1     list one file per line.  Avoid '\n' with -q or -b
```

</div></details>

`-b`制御文字をエスケープして表示する、`-q`制御文字を?で表示する、`-Q`ファイル名をダブルクォートで括って表示する、`-n`所有者とグループをIDで表示する、なども指定可能。
その他、ファイルサイズや時間表示のさらに細かいフォーマットの指定や、タブサイズや表示幅の指定といったオプションもあるが、使用頻度はあまり高くなさそう。

おすすめのオプションは
`-F ファイルの種類を記号で表示する`
`-h ファイルサイズを読みやすい単位で表示する（-lの指定が必要）`
`--full-time 更新日時をナノ秒まで表示し、タイムゾーンも表示する`
あたり。

### 表示順指定

lsコマンドの仕上げ。
ファイルリストの表示順を指定する。
主に下記のようなことをが可能。

* 更新日時などのタイムスタンプで並び替え
* ファイルサイズで並び替え
* ファイルの種類（拡張子）で並び替え
* 数字を辞書順ではなく自然な数字順で並び替え

```shell
# -t ファイルリストを更新日時の降順（最新ファイルが一番上）で並び替え
$ ls -lt
total 12
-rw-rw-r-- 1 ubuntu ubuntu   23 Dec 16 15:03 test.txt
lrwxrwxrwx 1 ubuntu ubuntu    4 Dec 16 14:14 usr -> /usr
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge

# -r ファイルリストの並び順を逆にする
$ ls -ltr
total 12
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo
lrwxrwxrwx 1 ubuntu ubuntu    4 Dec 16 14:14 usr -> /usr
-rw-rw-r-- 1 ubuntu ubuntu   23 Dec 16 15:03 test.txt

# -c ファイルリストをステータス更新日時(ctime)の降順で並び替え（-ltとの同時指定時）
$ ls -ltc
total 12
-rw-rw-r-- 1 ubuntu ubuntu   23 Dec 16 15:03 test.txt
lrwxrwxrwx 1 ubuntu ubuntu    4 Dec 16 14:14 usr -> /usr
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge
## リストに表示される時間もステータス更新日時になる
## -lcの指定だと、時間表示はステータス更新日時で名前順に表示
## -cのみの指定だと、ステータス更新日時順でファイル名のリストのみ表示

# -u ファイルリストをファイルアクセス日時(atime)の降順で並び替え（-ltとの同時指定時）
$ ls -ltu
total 12
-rw-rw-r-- 1 ubuntu ubuntu   23 Dec 19 14:48 test.txt
lrwxrwxrwx 1 ubuntu ubuntu    4 Dec 19 14:32 usr -> /usr
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:28 piyo
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 14 14:26 hoge
## リストに表示される時間もファイルアクセス日時になる
## -luの指定だと、時間表示はファイルアクセス日時で名前順に表示
## -uのみの指定だと、ファイルアクセス日時順でファイル名のリストのみ表示

# -S ファイルリストをファイルサイズの降順で並び替え
$ ls -lS /bin/
total 15320
-rwxr-xr-x 1 root root 2062296 Mar  6  2019 busybox
-rwxr-xr-x 1 root root 1113504 Jun  6  2019 bash
-rwxr-xr-x 1 root root  716464 Mar 12  2018 btrfs
-rwxr-xr-x 1 root root  584072 Sep  5 03:59 udevadm
-rwxr-xr-x 1 root root  554104 Feb 26  2018 ip
-rwxr-xr-x 1 root root  423312 Jan 21  2019 tar
・・・

# -X ファイルの拡張子で並び替え
## -Xを指定しない場合
$ ls -l
total 0
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.a
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.b
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.c
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.a
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.b
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.c

## -Xを指定した場合
$ ls -lX
total 0
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.a
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.a
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.b
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.b
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 hoge.c
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 19 15:30 piyo.c

# -v 自然な数字順で並び替え
## -vを指定しない場合（10、100が2の前に来る）
$ ls
1.so  10.so  100.so  2.so  20.so  200.so  3.so  30.so  300.so

## -vを指定した場合（数字順に並ぶ）
$ ls -v
1.so  2.so  3.so  10.so  20.so  30.so  100.so  200.so  300.so
```

<details><summary>表示順指定関連の全オプション</summary><div>

```
       -c     with  -lt: sort by, and show, ctime (time of last modification of file status information); with -l: show ctime and sort by
              name; otherwise: sort by ctime, newest first

       -f     do not sort, enable -aU, disable -ls --color

       --group-directories-first
              group directories before files;

              can be augmented with a --sort option, but any use of --sort=none (-U) disables grouping

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first

       -t     sort by modification time, newest first

       -u     with -lt: sort by, and show, access time; with -l: show access time and sort by name; otherwise: sort by access time,  new‐
              est first

       -U     do not sort; list entries in directory order

       -v     natural sort of (version) numbers within text

       -X     sort alphabetically by entry extension

       --sort=WORD
              sort by WORD instead of name: none (-U), size (-S), time (-t), version (-v), extension (-X)
```

</div></details>

`-f` `-U`並び替えを行わない、`--group-directories-first`ディレクトリを先に表示、なども指定可能。

よく使うオプションは
`-t ファイルリストを更新日時の降順（最新ファイルが一番上）で並び替え`
`-S ファイルリストをファイルサイズの降順で並び替え`
`-r ファイルリストの並び順を逆にする`
あたり。

### おまけ

ls以外でファイル情報を表示するコマンドとして、`stat`と`file`がある。
`stat`はファイルのシステム関連の情報、`file`はファイル形式の情報を表示できる。
さらに詳細情報を見たい場合に活用しましょう。

```shell
$ stat /bin/ls
  File: /bin/ls
  Size: 133792    	Blocks: 264        IO Block: 4096   regular file
Device: ca01h/51713d	Inode: 27          Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-12-19 06:25:04.969727807 +0000
Modify: 2018-01-18 09:43:49.000000000 +0000
Change: 2019-10-02 17:11:13.386742626 +0000
 Birth: -

$ file /bin/ls
/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9567f9a28e66f4d7ec4baf31cfbf68d0410f0ae6, stripped
```

## コマンド解説② findコマンド
```
$ whatis find
find (1)             - search for files in a directory hierarchy
```
ディレクトリ階層からファイル名などでファイルを検索するコマンド。
検証バージョンはこちら。

```
$ find --version
find (GNU findutils) 4.7.0-git
```

### 基本的な使い方

```shell
# 指定したパス配下から、指定したファイル名に一致するファイルを検索
## ファイル名にはワイルドカードを指定可能
## -printはファイル名を表示するというアクションの指定（省略可能）
## 下記は、/usr/bin/配下のディレクトリからファイル名の先頭がaptのファイルを検索してファイル名を表示する例
$ find /usr/bin/ -name 'apt*' -print
/usr/bin/apt
/usr/bin/apt-get
/usr/bin/apt-key
/usr/bin/apt-mark
/usr/bin/apt-extracttemplates
/usr/bin/apt-sortpkgs
/usr/bin/apt-ftparchive
/usr/bin/apt-config
/usr/bin/apt-add-repository
/usr/bin/apt-cache
/usr/bin/apt-cdrom

# パスを省略するとカレントディレクトリを検索
$ find -name 'hoge' -print
./hoge

# 見つけたファイルに対して、コマンド実行をすることも可能
$ find -name 'hoge' -exec file '{}' \;
./hoge: directory
```

findコマンドを使う際にシェル展開がされないようにする必要があるため、制御文字を'apt*'、'{}'のようにシングルクォートで括ったり、\;のようにエスケープをする必要がある。

### 全体を俯瞰してみる

findコマンドの使用方法で肝となるのが、引数の指定順と式の理解。

```:書式
$ find [オプション] [検索するパス...] [式]
```

```:使用例
$ find -P /usr/bin/ -name 'apt*' -print
```
コマンドの後にオプションが来るのはlsコマンドなどの一般的なコマンドと一緒だが、オプションの位置に指定できるものは限られており、あまり頻繁には使わないものが多い。よく使う`-name`などは式なので、これらの検索条件は検索するパスの後ろに指定する。
そのためfindコマンドは、下記のように`find`のすぐ後にパスを指定し、その後にオプションのようなものを指定する形式になることが多い。
`$ find /usr/bin/ -name 'apt*' -print`

一見すると一般的なコマンドとはオプション類の指定順が逆のように見えるが、パスを指定してから式を記載するという書式にまず慣れるのがfindに親しむコツ。
式に指定可能なものは下記に分けられる。

|カテゴリ|説明|オプション数|
|:-:|:-:|:-:|
|位置オプション|指定した箇所から後ろの式に影響があるオプション<br>警告メッセージの表示有無などを指定する|4|
|グローバルオプション|どこに指定しても全体に影響があるオプション<br>指定されたパスの何階層目までを検索するかなどを指定する|11|
|演算子|ANDやORなど、条件の論理演算方法を指定する|7|
|検査|検索条件などを指定する|45|
|アクション|コマンドなどを実行する|17|

式の中でも、どんな条件でファイルを検索するかという「検査」と、検索条件に合致したファイルに対して何をするかという「アクション」がfindコマンドのメイン。

findコマンドを使う際には下記の順で考えてコマンドを組み立てるのがよさそう。

**　検索の前提条件（リンク先まで検索するか、警告メッセージを表示するか、何階層目まで検索するかなど）を決め、**
**　「検索するパスの前に指定できるオプション」、「位置オプション」、「グローバルオプション」として指定する**
**　↓**
**　検索するファイル名やファイルタイプなどの検索条件を決め、**
**　「検査」として指定する。ORやANDなどが含まれる条件は「演算子」を使用して表現する**
**　↓**
**　検索条件に合致したファイルに対して何をしたいかを決め、**
**　「アクション」として指定する**

lsコマンドもオプションが多いと感じたが、findコマンドはさらに指定できるオプションが多く、何よりmanページのボリュームがヤバイ。

```
$ man ls | wc -c
7760
$ man find | wc -c
72785
```

ちなみに複雑なコマンドとしてまず頭に浮かぶawkコマンドのmanページは下記の通り。

```
$ man awk | wc -c
90017
```
awkといい勝負をするとは、やるなfind。
かなり骨がありそうですが、仲良くなればかなり心強い味方になってくれるはず。
さあ張り切って進めていきましょう。

### オプション

検索するパスの前に指定できるオプション。全部で5種類。
主に下記のようなことを指定可能。

* リンク先も検索するか
* デバッグ情報を表示するか
* 使用する最適化ロジック

```shell
# -P リンク先は検索しない（デフォルトの動作）
$ ls -l usr
lrwxrwxrwx 1 ubuntu ubuntu 4 Dec 16 14:14 usr -> /usr
$ find -P usr -name 'usr'
usr
## リンク先は検索せず、リンク自体の情報を表示する

# -H コマンドラインに指定されたものはリンク先を検索する
$ ls -l usr
lrwxrwxrwx 1 ubuntu ubuntu 4 Dec 16 14:14 usr -> /usr
$ find -H usr -name 'usr'
usr
usr/src/linux-headers-4.15.0-1051-aws/usr
usr/src/linux-headers-4.15.0-1056-aws/usr
usr/src/linux-aws-headers-4.15.0-1056/usr
usr/src/linux-aws-headers-4.15.0-1051/usr
usr/share/gdb/auto-load/usr

# -L サブディレクトリにあるものも含めて全てのリンク先を検索する
$ ls -l usr
lrwxrwxrwx 1 ubuntu ubuntu 4 Dec 16 14:14 usr -> /usr
$ find -L usr -name 'usr'
usr
usr/src/linux-headers-4.15.0-1051-aws/usr
usr/src/linux-headers-4.15.0-1056-aws/usr
usr/src/linux-aws-headers-4.15.0-1056/usr
usr/src/linux-aws-headers-4.15.0-1051/usr
usr/share/gdb/auto-load/usr
find: ‘usr/lib/ssl/private’: Permission denied
find: File system loop detected; ‘usr/bin/X11’ is part of the same file system loop as ‘usr/bin’.
## 検索先が非常に多くなる可能性があるので注意
## また、リンクがループしてエラーが出ることがある
```

<details><summary>manページ記載の全オプション</summary><div>

```
OPTIONS
       The  -H,  -L and -P options control the treatment of symbolic links.  Command-line arguments following these are taken to be names
       of files or directories to be examined, up to the first argument that begins with `-', or the argument `(' or `!'.  That  argument
       and any following arguments are taken to be the expression describing what is to be searched for.  If no paths are given, the cur‐
       rent directory is used.  If no expression is given, the expression -print is used (but you should probably consider using  -print0
       instead, anyway).

       This  manual page talks about `options' within the expression list.  These options control the behaviour of find but are specified
       immediately after the last path name.  The five `real' options -H, -L, -P, -D and -O must appear before the first path name, if at
       all.   A  double  dash  -- can also be used to signal that any remaining arguments are not options (though ensuring that all start
       points begin with either `./' or `/' is generally safer if you use wildcards in the list of start points).

       -P     Never follow symbolic links.  This is the default behaviour.  When find examines or prints information a file, and the file
              is a symbolic link, the information used shall be taken from the properties of the symbolic link itself.

       -L     Follow  symbolic links.  When find examines or prints information about files, the information used shall be taken from the
              properties of the file to which the link points, not from the link itself (unless it is a broken symbolic link or  find  is
              unable to examine the file to which the link points).  Use of this option implies -noleaf.  If you later use the -P option,
              -noleaf will still be in effect.  If -L is in effect and find discovers a  symbolic  link  to  a  subdirectory  during  its
              search, the subdirectory pointed to by the symbolic link will be searched.

              When  the  -L  option is in effect, the -type predicate will always match against the type of the file that a symbolic link
              points to rather than the link itself (unless the symbolic link is broken).  Actions  that  can  cause  symbolic  links  to
              become  broken  while  find  is  executing (for example -delete) can give rise to confusing behaviour.  Using -L causes the
              -lname and -ilname predicates always to return false.

       -H     Do not follow symbolic links, except while processing the command line arguments.  When find examines or prints information
              about  files,  the information used shall be taken from the properties of the symbolic link itself.   The only exception to
              this behaviour is when a file specified on the command line is a symbolic link, and the link can  be  resolved.   For  that
              situation, the information used is taken from whatever the link points to (that is, the link is followed).  The information
              about the link itself is used as a fallback if the file pointed to by the symbolic link cannot be examined.  If  -H  is  in
              effect and one of the paths specified on the command line is a symbolic link to a directory, the contents of that directory
              will be examined (though of course -maxdepth 0 would prevent this).

       If more than one of -H, -L and -P is specified, each overrides the others; the last  one  appearing  on  the  command  line  takes
       effect.  Since it is the default, the -P option should be considered to be in effect unless either -H or -L is specified.

       GNU  find  frequently stats files during the processing of the command line itself, before any searching has begun.  These options
       also affect how those arguments are processed.  Specifically, there are a number of tests that compare files listed on the command
       line  against  a  file we are currently considering.  In each case, the file specified on the command line will have been examined
       and some of its properties will have been saved.  If the named file is in fact a symbolic link, and the -P option is in effect (or
       if  neither  -H  nor -L were specified), the information used for the comparison will be taken from the properties of the symbolic
       link.  Otherwise, it will be taken from the properties of the file the link points to.  If find cannot follow the link (for  exam‐
       ple  because  it  has  insufficient privileges or the link points to a nonexistent file) the properties of the link itself will be
       used.

       When the -H or -L options are in effect, any symbolic links listed as the argument of -newer will be dereferenced, and  the  time‐
       stamp  will  be  taken  from  the file to which the symbolic link points.  The same consideration applies to -newerXY, -anewer and
       -cnewer.

       The -follow option has a similar effect to -L, though it takes effect at the point where it appears (that is, if -L  is  not  used
       but  -follow  is,  any  symbolic  links appearing after -follow on the command line will be dereferenced, and those before it will
       not).

       -D debugopts
              Print diagnostic information; this can be helpful to diagnose problems with why find is not doing what you want.  The  list
              of debug options should be comma separated.  Compatibility of the debug options is not guaranteed between releases of find‐
              utils.  For a complete list of valid debug options, see the output of find -D help.  Valid debug options include

              exec   Show diagnostic information relating to -exec, -execdir, -ok and -okdir

              help   Explain the debugging options.

              opt    Prints diagnostic information relating to the optimisation of the expression tree; see the -O option.

              rates  Prints a summary indicating how often each predicate succeeded or failed.

              search Navigate the directory tree verbosely.

              stat   Print messages as files are examined with the stat and lstat system calls.  The find program tries to minimise  such
                     calls.

              tree   Show the expression tree in its original and optimised form.

       -Olevel
              Enables  query  optimisation.    The find program reorders tests to speed up execution while preserving the overall effect;
              that is, predicates with side effects are not reordered relative to each other.  The optimisations performed at each  opti‐
              misation level are as follows.

              0      Equivalent to optimisation level 1.

              1      This  is  the default optimisation level and corresponds to the traditional behaviour.  Expressions are reordered so
                     that tests based only on the names of files (for example -name and -regex) are performed first.

              2      Any -type or -xtype tests are performed after any tests based only on the names of files, but before any tests  that
                     require  information  from  the inode.  On many modern versions of Unix, file types are returned by readdir() and so
                     these predicates are faster to evaluate than predicates which need to stat the file first.  If you use  the  -fstype
                     FOO  predicate  and  specify  a filesystem type FOO which is not known (that is, present in `/etc/mtab') at the time
                     find starts, that predicate is equivalent to -false.

              3      At this optimisation level, the full cost-based query optimiser is enabled.  The order of tests is modified so  that
                     cheap  (i.e. fast) tests are performed first and more expensive ones are performed later, if necessary.  Within each
                     cost band, predicates are evaluated earlier or later according to whether they are likely to succeed  or  not.   For
                     -o,  predicates  which  are likely to succeed are evaluated earlier, and for -a, predicates which are likely to fail
                     are evaluated earlier.

              The cost-based optimiser has a fixed idea of how likely any given test is to succeed.  In some cases the probability  takes
              account  of  the  specific  nature of the test (for example, -type f is assumed to be more likely to succeed than -type c).
              The cost-based optimiser is currently being evaluated.   If it does not actually improve the performance of find,  it  will
              be  removed again.  Conversely, optimisations that prove to be reliable, robust and effective may be enabled at lower opti‐
              misation levels over time.  However, the default behaviour (i.e. optimisation level 1) will not be  changed  in  the  4.3.x
              release series.  The findutils test suite runs all the tests on find at each optimisation level and ensures that the result
              is the same.
```

</div></details>

`-D`デバッグ情報を表示する、`-O`最適化ロジックを指定する、といったオプションもある。`-D`は複雑な検索条件を指定していて判定ロジックの途中経過が見たい時、`-O`はfindコマンド実行時に性能が出ない時に使うとよさそう。

### 位置オプション

指定した箇所から後ろの式に影響があるオプション。
主に下記のようなことを指定可能。

* 「検査」に時間を指定した場合の今日の始まりの考え方  
  （24時間前を今日の始まりとするか、0時を今日の始まりとするか）
* コマンド実行時の警告メッセージを表示するか
* 使用する正規表現タイプ

```shell
# -daystart 今日の始まりをコマンド実行当日の0時にする
## 1月1日の12時に、今日更新されたファイルを検索した場合の例で説明
$ date
Wed Jan  1 12:00:00 UTC 2020
$ ls -l
total 8
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 31 21:00 hoge
drwxrwxr-x 2 ubuntu ubuntu 4096 Jan  1  9:00 piyo

## -daystartの指定なし
## 24時間以内に更新されたファイル（12月31日の12時〜1月1日の12時前までに更新されたファイル）を表示
$ find -mtime 0 -ls
   268594      4 drwxrwxr-x   2 ubuntu   ubuntu       4096 Dec 31 21:00 ./hoge
   283029      4 drwxrwxr-x   2 ubuntu   ubuntu       4096 Jan  1  9:00 ./piyo
## -lsはファイルリストをロングフォーマットで表示するコマンド（詳細は「アクション」の項目参照）

## -daystartの指定あり
## コマンド実行当日の1月1日に更新されたファイル（1月1日の0時〜1月1日の24時前までに更新されたファイル）を表示
$ find -daystart -mtime 0
   283029      4 drwxrwxr-x   2 ubuntu   ubuntu       4096 Jan  1  9:00 ./piyo

# -nowarn 警告メッセージを表示しない
## -nowarn指定なしの場合
$ find -name 'hoge' -maxdepth 1
find: warning: you have specified the -maxdepth option after a non-option argument -name, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it).  Please specify options before other arguments.

./hoge
## コマンド利用方法に関する警告メッセージが表示される
## 上記の例ではグローバルオプションである-maxdepthを式の最初に指定していないことで警告が出ている

## -nowarn指定ありの場合
$ find -nowarn -name 'hoge' -maxdepth 1
./hoge
## 警告メッセージは表示されない

## findコマンド使用時によく遭遇する「Permission denied」はエラー出力なので、-nowarnでは消せない
$ find /root/ -nowarn
/root/
find: ‘/root/’: Permission denied

## エラー出力を消したい時は、リダイレクトで捨てる
$ find /root/ 2> /dev/null
/root/

# -regextype 使用する正規表現タイプの指定
## findコマンドのデフォルトの正規表現はemacs
## emacs正規表現はエスケープが必要だったり使えない正規表現があったりするので、
## 拡張正規表現（posix-extended）の指定がおすすめ
$ find -regextype posix-extended -regex '.*(hoge|piyo){2}'
./piyopiyo
./hogehoge
```

<details><summary>manページ記載の全位置オプション</summary><div>

```
   POSITIONAL OPTIONS
       Positional options always return true.  They affect only tests occurring later on the command line.

       -daystart
              Measure  times  (for -amin, -atime, -cmin, -ctime, -mmin, and -mtime) from the beginning of today rather than from 24 hours
              ago.  This option only affects tests which appear later on the command line.

       -follow
              Deprecated; use the -L option instead.  Dereference symbolic links.  Implies -noleaf.   The  -follow  option  affects  only
              those  tests which appear after it on the command line.  Unless the -H or -L option has been specified, the position of the
              -follow option changes the behaviour of the -newer predicate; any files listed as the argument of -newer will  be  derefer‐
              enced  if  they are symbolic links.  The same consideration applies to -newerXY, -anewer and -cnewer.  Similarly, the -type
              predicate will always match against the type of the file that a symbolic link points to rather than the link itself.  Using
              -follow causes the -lname and -ilname predicates always to return false.

       -regextype type
              Changes the regular expression syntax understood by -regex and -iregex tests which occur later on the command line.  To see
              which regular expression types are known, use -regextype help.  The Texinfo documentation (see SEE ALSO) explains the mean‐
              ing of and differences between the various types of regular expression.

       -warn, -nowarn
              Turn  warning  messages  on  or  off.  These warnings apply only to the command line usage, not to any conditions that find
              might encounter when it searches directories.  The default behaviour corresponds to -warn if standard input is a  tty,  and
              to  -nowarn  otherwise.   If  a  warning message relating to command-line usage is produced, the exit status of find is not
              affected.  If the POSIXLY_CORRECT environment variable is set, and -warn is also used, it is not specified which,  if  any,
              warnings will be active.
```

</div></details>

リンク先を検索する`-follow`もあるが非推奨。代わりにオプションの`-L`を使いましょう。

### グローバルオプション

どこに指定しても全体に影響があるオプション。
主に下記のようなことを指定可能。

* ディレクトリ自体よりも先に、ディレクトリの中身を検索するか  
* 指定されたパスの何階層目までを検索するか
* 指定されたパスから何階層目までを検索対象外とするか

```shell
# -depth ディレクトリ自体よりも先に、ディレクトリの中身を検索する
## 下記構成のディレクトリを検索
$ tree hoge
hoge
├── hoge.txt
└── piyo
    └── piyo.txt

## -depthを指定しない場合
$ find hoge
hoge
hoge/piyo
hoge/piyo/piyo.txt
hoge/hoge.txt

## -depthを指定した場合
$ find hoge -depth
hoge/piyo/piyo.txt
hoge/piyo
hoge/hoge.txt
hoge

# -maxdepth 指定されたパスの何階層目までを検索するかを指定
# -mindepth 指定されたパスの何階層目までを検索対象外とするかを指定
## 下記構成のディレクトリを検索
$ tree hoge
hoge
├── hoge.txt
└── piyo
    └── piyo.txt

## -maxdepth、-mindepthともに指定しない場合
$ find hoge
hoge
hoge/piyo
hoge/piyo/piyo.txt
hoge/hoge.txt

## -maxdepth 0 の場合は指定されたパスのみ
$ find hoge -maxdepth 0
hoge

## -maxdepth 1 の場合は1階層目までを検索
$ find hoge -maxdepth 1
hoge
hoge/piyo
hoge/hoge.txt

## -mindepth 2 の場合は2階層目以降を検索（1階層目までを検索対象外とする）
$ find hoge -mindepth 2
hoge/piyo/piyo.txt

## 同時指定も可能
$ find hoge -mindepth 1　-maxdepth 2 
hoge/piyo
hoge/piyo/piyo.txt
hoge/hoge.txt
```

<details><summary>manページ記載の全グローバルオプション</summary><div>

```
   GLOBAL OPTIONS
       Global options always return true.  Global options take effect even for tests which occur earlier on the command line.  To prevent
       confusion, global options should specified on the command-line after the list of start points, just before the first  test,  posi‐
       tional  option  or  action.  If you specify a global option in some other place, find will issue a warning message explaining that
       this can be confusing.

       The global options occur after the list of start points, and so are not the same kind of option as -L, for example.

       -d     A synonym for -depth, for compatibility with FreeBSD, NetBSD, MacOS X and OpenBSD.

       -depth Process each directory's contents before the directory itself.  The -delete action also implies -depth.

       -help, --help
              Print a summary of the command-line usage of find and exit.

       -ignore_readdir_race
              Normally, find will emit an error message when it fails to stat a file.  If you give this option  and  a  file  is  deleted
              between  the  time find reads the name of the file from the directory and the time it tries to stat the file, no error mes‐
              sage will be issued.    This also applies to files or directories whose names are given on the command line.   This  option
              takes  effect at the time the command line is read, which means that you cannot search one part of the filesystem with this
              option on and part of it with this option off (if you need to do that, you will need to issue two  find  commands  instead,
              one with the option and one without it).

       -maxdepth levels
              Descend at most levels (a non-negative integer) levels of directories below the starting-points.  -maxdepth 0
               means only apply the tests and actions to the starting-points themselves.

       -mindepth levels
              Do not apply any tests or actions at levels less than levels (a non-negative integer).  -mindepth 1 means process all files
              except the starting-points.

       -mount Don't descend directories on other filesystems.  An alternate name for -xdev, for compatibility with some other versions of
              find.

       -noignore_readdir_race
              Turns off the effect of -ignore_readdir_race.

       -noleaf
              Do  not  optimize  by  assuming that directories contain 2 fewer subdirectories than their hard link count.  This option is
              needed when searching filesystems that do not follow the Unix directory-link convention, such as CD-ROM or MS-DOS  filesys‐
              tems  or  AFS  volume mount points.  Each directory on a normal Unix filesystem has at least 2 hard links: its name and its
              `.'  entry.  Additionally, its subdirectories (if any) each have a `..' entry linked to that directory.  When find is exam‐
              ining  a  directory, after it has statted 2 fewer subdirectories than the directory's link count, it knows that the rest of
              the entries in the directory are non-directories (`leaf' files in the directory tree).  If only the files' names need to be
              examined, there is no need to stat them; this gives a significant increase in search speed.

       -version, --version
              Print the find version number and exit.

       -xdev  Don't descend directories on other filesystems.
```

</div></details>

下記のようなオプションもある。
`-mount` 別のファイルシステムにあるディレクトリを検索しない（`-xdev`も同様）
`-ignore_readdir_race` ファイル情報を取得できなかった場合にエラー表示をしない
`-noleaf` .（カレントディレクトリ）と..（親ディレクトリ）がディレクトリに必ずある前提での最適化を行わない（CD-ROM、MS-DOSなどLinuxファイルシステム以外のディレクトリを検索する場合に使用）
  
`-help`や`-version`もグローバルオプション。


### 演算子

ANDやORなど、条件の論理演算方法を指定する。
下記のようなことが可能。

* ()での優先順位指定
* AND演算
* OR演算
* NOT演算
* カンマ演算（リスト）

```shell
# -and AND演算（-andは省略可能。-aでも可）
$ find -name '*hoge*' -and -name '*piyo*'
./hogepiyo
## 左辺がfalseの場合は右辺は評価しない

# -or OR演算（-oでも可）
$ find -name 'hoge' -or -name 'piyo'
./piyo
./hoge
## 左辺がtrueの場合は右辺は評価しない

# -not NOT演算（!でも可）
$ ls
hoge  piyo
$ find -not -name 'hoge'
.
./piyo

# expr1 , expr2 カンマ演算（リスト）
## expr1とexpr2の両方を必ず評価する。リスト全体の値はexpr2の値となる
$ find -false -and -name 'hoge'
$ find -false , -name 'hoge'
./hoge
## -andの場合は左辺がfalseだと右辺の処理を行わないが、リストの場合は必ず右辺も評価される
## （-falseは常にfalseを返す式）
## カンマ演算は、アクションが途中で失敗しても以降の処理を継続させたい場合などに使用する
```

<details><summary>manページ記載の全演算子</summary><div>

```
   OPERATORS
       Listed in order of decreasing precedence:

       ( expr )
              Force precedence.  Since parentheses are special to the shell, you will normally need to quote them.  Many of the  examples
              in this manual page use backslashes for this purpose: `\(...\)' instead of `(...)'.

       ! expr True if expr is false.  This character will also usually need protection from interpretation by the shell.

       -not expr
              Same as ! expr, but not POSIX compliant.

       expr1 expr2
              Two expressions in a row are taken to be joined with an implied -a; expr2 is not evaluated if expr1 is false.

       expr1 -a expr2
              Same as expr1 expr2.

       expr1 -and expr2
              Same as expr1 expr2, but not POSIX compliant.

       expr1 -o expr2
              Or; expr2 is not evaluated if expr1 is true.

       expr1 -or expr2
              Same as expr1 -o expr2, but not POSIX compliant.

       expr1 , expr2
              List;  both  expr1  and expr2 are always evaluated.  The value of expr1 is discarded; the value of the list is the value of
              expr2.  The comma operator can be useful for searching for several different types of thing, but traversing the  filesystem
              hierarchy  only  once.   The  -fprintf  action  can be used to list the various matched items into several different output
              files.

       Please note that -a when specified implicitly (for example by two tests appearing without an explicit operator  between  them)  or
       explicitly has higher precedence than -o.  This means that find . -name afile -o -name bfile -print will never print afile.
```

</div></details>

### 検査

findコマンドの中心的存在。
どんな条件でファイルを検索するかを指定する。
主に下記のようなことが可能。

* ファイル名、パス名検索
* タイムスタンプ検索
* ファイルの属性（ファイルタイプ、パーミッション、サイズなど）検索

数が多いので、カテゴリ毎に見ていきましょう。

#### ファイル名、パス名検索

```shell:
# -name pattern ファイル名を検索
$ find -name 'hoge'
./hoge

# -path pattern パスを検索
$ find /etc/ -path '*kernel*' 2> /dev/null
/etc/apt/apt.conf.d/01autoremove-kernels
/etc/apparmor.d/tunables/kernelvars
/etc/kernel
/etc/kernel/install.d
/etc/kernel/postinst.d
/etc/kernel/postinst.d/zz-update-grub
/etc/kernel/postinst.d/update-notifier
/etc/kernel/postinst.d/x-grub-legacy-ec2
/etc/kernel/postinst.d/apt-auto-removal
/etc/kernel/postinst.d/initramfs-tools
/etc/kernel/postinst.d/unattended-upgrades
/etc/kernel/postrm.d
/etc/kernel/postrm.d/zz-update-grub
/etc/kernel/postrm.d/x-grub-legacy-ec2
/etc/kernel/postrm.d/initramfs-tools
/etc/sysctl.d/10-kernel-hardening.conf
/etc/kernel-img.conf

# -lname pattern リンク先のパスを検索
$ find -lname '*local*' -ls
   256325      0 lrwxrwxrwx   1 ubuntu   ubuntu         14 Dec 24 15:04 ./bin -> /usr/local/bin

# -regex pattern 正規表現でパスを検索
## 拡張正規表現を使えるように、-regextype posix-extendedの同時指定がおすすめ
$ find /usr/ -regextype posix-extended -regex '.*[0-9]\.[0-9]{2}\.[0-9]-[0-9]{4}.*selinux'
/usr/src/linux-headers-4.15.0-1051-aws/scripts/selinux
/usr/src/linux-headers-4.15.0-1051-aws/include/config/security/selinux
/usr/src/linux-headers-4.15.0-1056-aws/scripts/selinux
/usr/src/linux-headers-4.15.0-1056-aws/include/config/security/selinux
/usr/src/linux-aws-headers-4.15.0-1056/scripts/selinux
/usr/src/linux-aws-headers-4.15.0-1056/security/selinux
/usr/src/linux-aws-headers-4.15.0-1051/scripts/selinux
/usr/src/linux-aws-headers-4.15.0-1051/security/selinux
```

大文字小文字を区別しない`-iname` `-ipath` `-ilname` `-iregex`もある。

#### タイムスタンプ検索

```shell:
# -mmin n 更新日時がn分前のファイルを検索
# -mmin +n 更新日時がn分前より古いファイルを検索
# -mmin -n 更新日時がn分前より新しいファイルを検索
## 12時00分00秒にファイルを検索した場合の例で説明
$ date
Wed Jan  1 12:00:00 UTC 2020
$ touch -d '2020-1-1 11:57:00.000000001' 11:57:00.000000001.txt
$ touch -d '2020-1-1 11:58:00.000000001' 11:58:00.000000001.txt
$ touch -d '2020-1-1 11:59:00.000000001' 11:59:00.000000001.txt
## 境界値を含まないことを示すため、時間を1ナノ秒だけずらして設定
## 以降の説明では、「○：境界値を含まない」、「●：境界値を含む」の記号を用いる

## 更新日時が1分前未満〜現在（○11:59:00〜●12:00:00）のファイルを検索
$ find -mmin 1
./11:59:00.000000001.txt

## 更新日時が2分前未満〜1分前（○11:58:00〜●11:59:00）のファイルを検索
$ find -mmin 2
./11:58:00.000000001.txt

## 更新日時が3分前未満〜2分前（○11:57:00〜●11:58:00）のファイルを検索
$ find -mmin 3
./11:57:00.000000001.txt

## 更新日時が1分前より古いファイル（過去〜○11:59:00）を検索
$ find -mmin +1
./11:57:00.000000001.txt
./11:58:00.000000001.txt

## 更新日時が2分前より古いファイル（過去〜○11:58:00）を検索
$ find -mmin +2
./11:57:00.000000001.txt

## 更新日時が3分前より古いファイル（過去〜○11:57:00）を検索
$ find -mmin +3
### 該当なし

## 更新日時が1分前より新しいファイル（○11:59:00〜現在）を検索
$ find -mmin -1
./11:59:00.000000001.txt

## 更新日時が2分前より新しいファイル（○11:58:00〜現在）を検索
$ find -mmin -2
./11:58:00.000000001.txt
./11:59:00.000000001.txt

## 更新日時が3分前より新しいファイル（○11:57:00〜現在）を検索
$ find -mmin -3
./11:57:00.000000001.txt
./11:58:00.000000001.txt
./11:59:00.000000001.txt

# -mtime n 更新日時がn日前のファイルを検索
# -mtime +n 更新日時がn日前より古いファイルを検索
# -mtime -n 更新日時がn日前より新しいファイルを検索
## 1月1日の12時にファイルを検索した場合の例で説明
$ date
Wed Jan  1 12:00:00 UTC 2020
$ touch -d '2019-12-28 12:00:00.000000001' 2019-12-28_12:00:00.000000001.txt
$ touch -d '2019-12-29 12:00:00.000000001' 2019-12-29_12:00:00.000000001.txt
$ touch -d '2019-12-30 12:00:00.000000001' 2019-12-30_12:00:00.000000001.txt
$ touch -d '2019-12-31 12:00:00.000000001' 2019-12-31_12:00:00.000000001.txt
## 境界値を含まないことを示すため、時間を1ナノ秒だけずらして設定
## 位置オプションの-daystartは使用しない場合の例

## 更新日が1日前未満〜現在（○2019-12-31 12:00:00〜●2020-1-1 12:00:00）のファイルを検索
$ find -mtime 0
./2019-12-31_12:00:00.000000001.txt

## 更新日が2日前未満〜1日前（○2019-12-30 12:00:00〜●2019-12-31 12:00:00）のファイルを検索
$ find -mtime 1
./2019-12-30_12:00:00.000000001.txt

## 更新日が3日前未満〜2日前（○2019-12-29 12:00:00〜●2019-12-30 12:00:00）のファイルを検索
$ find -mtime 2
./2019-12-29_12:00:00.000000001.txt

## 更新日が4日前未満〜3日前（○2019-12-28 12:00:00〜●2019-12-29 12:00:00）のファイルを検索
$ find -mtime 3
./2019-12-28_12:00:00.000000001.txt

## 更新日時が1日前より古いファイル（過去〜●2019-12-31 12:00:00）を検索
$ find -mtime +0
./2019-12-28_12:00:00.000000001.txt
./2019-12-29_12:00:00.000000001.txt
./2019-12-30_12:00:00.000000001.txt

## 更新日時が2日前より古いファイル（過去〜●2019-12-30 12:00:00）を検索
$ find -mtime +1
./2019-12-28_12:00:00.000000001.txt
./2019-12-29_12:00:00.000000001.txt

## 更新日時が3日前より古いファイル（過去〜●2019-12-29 12:00:00）を検索
$ find -mtime +2
./2019-12-28_12:00:00.000000001.txt

## 更新日時が4日前より古いファイル（過去〜●2019-12-28 12:00:00）を検索
$ find -mtime +3
### 該当なし

## 更新日時が0日前より新しいファイル（○2020-1-1 12:00:00〜現在）を検索
$ find -mtime -0
### 常に現在と一致するため、どのファイルとも一致しない

## 更新日時が1日前より新しいファイル（○2019-12-31 12:00:00〜現在）を検索
$ find -mtime -1
./2019-12-31_12:00:00.000000001.txt

## 更新日時が2日前より新しいファイル（○2019-12-30 12:00:00〜現在）を検索
$ find -mtime -2
./2019-12-31_12:00:00.000000001.txt
./2019-12-30_12:00:00.000000001.txt

## 更新日時が3日前より新しいファイル（○2019-12-29 12:00:00〜現在）を検索
$ find -mtime -3
./2019-12-31_12:00:00.000000001.txt
./2019-12-30_12:00:00.000000001.txt
./2019-12-29_12:00:00.000000001.txt

## 実動作は上記の通りだが、mminとmtimeは0の扱いと+-指定時の境界の考え方が異なるためややこしい
## きちんと理解したい人は、後述の「mminとmtimeの仕様差異」を見てみてください

# -newer file 指定したファイルの更新日時より新しいファイルを検索
$ ls -l
total 0
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 21 12:00 2019-12-21.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 22 12:00 2019-12-22.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 23 12:00 2019-12-23.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 24 12:00 2019-12-24.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 25 12:00 2019-12-25.txt
$ find -newer 2019-12-23.txt
./2019-12-24.txt
./2019-12-25.txt

## ファイルのアクセス日時で検索する-amin、-atime、-anewer、
## ファイルのステータス更新日時で検索する-cmin、-ctime、-cnewerもある

# -newermt STRING 指定した日時よりも更新日時が新しいファイルを検索
$ find -newermt '2019-12-23'
./2019-12-23.txt
./2019-12-24.txt
./2019-12-25.txt

## 論理演算子と組み合わせて範囲を検索することも可能
$ find -newermt '2019-12-22' -not -newermt '2019-12-25'
./2019-12-22.txt
./2019-12-23.txt
./2019-12-24.txt

## ファイルのアクセス日時で検索する-newerat、
## ファイルのステータス更新日時で検索する-newerct、
## ファイルの作成日時で検索する-newerBtもある
## （ただし-newerBtはサポートされていないシステムもある）
```

下記のようなオプションもある。
`-used n`ファイルのアクセス日時がステータス更新日時よりn日後のファイルを検索

##### mminとmtimeの仕様差異
mminとmtimeは、0の扱いと+-指定時の境界の考え方に仕様差異があるため、そこを理解して使用しないと混乱の元となる。

**0の扱いの違い**
mmin：0を使用せず、引数に指定する数字は1から始まる。0分〜1分未満を検索する場合は`-mmin 1`
mtime：0を使用し、引数に指定する数字は0から始まる。0日〜1日未満を検索する場合は`-mtime 0`

**+-指定時の境界の考え方**
mmin：+-指定時の境界値は点を指す。そのため、+の範囲と-の範囲は境界値の1点を除いて連続する範囲となる
`-mmin +1`：過去〜○11:59:00
`-mmin -1`：○11:59:00〜現在
どちらにも含まない範囲：●11:59:00
※ちなみに+-指定のない`mmin 1`は「○11:59:00〜●12:00:00」を指すため、`-mmin -1`の範囲と重複がある

mtime：+-指定時の境界値は範囲を指す。そのため、+の範囲と-の範囲は、連続する範囲とならない（24時間分を空けた範囲となる）
`-mtime +1`：過去〜●2019-12-30 12:00:00
`-mtime -1`：○2019-12-31 12:00:00〜現在
どちらにも含まない範囲：○2019-12-30 12:00:00〜●2019-12-31 12:00:00
※ちなみに+-指定のない`mtime 1`は「○2019-12-30 12:00:00〜●2019-12-31 12:00:00」を指すため、`-mtime +1` `-mtime -1` `mtime 1`の範囲を全てを合わせると、連続した範囲になる

どうして仕様を統一しないんだろう。。
理由を知っている人がいたら教えてください。

#### ファイルの属性（ファイルタイプ、パーミッション、サイズなど）検索

```shell:
# ファイルタイプの検索
# -type f ファイルを検索
# -type d ディレクトリを検索
# -type l リンクを検索
$ ls -l
total 4
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 26 14:32 dir
-rw-rw-r-- 1 ubuntu ubuntu    0 Dec 26 14:32 file
lrwxrwxrwx 1 ubuntu ubuntu    1 Dec 26 14:33 link -> /
$ find -type f
./file
$ find -type d
.
./dir
$ find -type l
./link

# ファイルパーミッションの検索
## 下記のファイルに対してコマンドを実行した場合の例で説明
$ ls -l
total 0
-r-------- 1 ubuntu ubuntu 0 Dec 26 14:59 400.txt
-r--r----- 1 ubuntu ubuntu 0 Dec 26 14:58 440.txt
-rw------- 1 ubuntu ubuntu 0 Dec 26 14:57 600.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 26 14:56 664.txt
-rw-rw-rw- 1 ubuntu ubuntu 0 Dec 26 14:56 666.txt
-rwxrwxr-x 1 ubuntu ubuntu 0 Dec 26 14:58 775.txt
-rwxrwxrwx 1 ubuntu ubuntu 0 Dec 26 14:56 777.txt

# -readable 読み込み可能なファイルを検索
$ find -readable
.
./400.txt
./440.txt
./600.txt
./664.txt
./666.txt
./775.txt
./777.txt

# -writable 書き込み可能なファイルを検索
$ find -writable
.
./600.txt
./664.txt
./666.txt
./775.txt
./777.txt

# -executable 実行可能なファイルを検索
$ find -executable
.
./775.txt
./777.txt

# -perm XXX 引数に指定したパーミッションと完全に一致するファイルを検索
$ find -perm 664
./664.txt

# -perm -XXX 引数に指定したパーミッションが含まれるファイルを検索
$ find -perm -664
.
./664.txt
./666.txt
./775.txt
./777.txt

# -perm /XXX 引数に指定したパーミッションのいずれかが一致するファイルを検索
$ find -perm /444
.
./400.txt
./440.txt
./600.txt
./664.txt
./666.txt
./775.txt
./777.txt

# -size n サイズがnブロックのファイルを検索（1ブロックは512バイト）
# -size +n サイズがnブロックより大きいファイルを検索（1ブロックは512バイト）
# -size -n サイズがnブロックより小さいファイルを検索（1ブロックは512バイト）
## nに接尾辞をつけることでサイズの単位を指定できる
## c：バイト、k：キビバイト、M：メビバイト、G：ギビバイト
$ ls -l /var/log/syslog.*
-rw-r----- 1 syslog adm 18401 Dec 27 06:25 /var/log/syslog.1
-rw-r----- 1 syslog adm  1625 Dec 26 06:25 /var/log/syslog.2.gz
-rw-r----- 1 syslog adm  1618 Dec 25 06:25 /var/log/syslog.3.gz
-rw-r----- 1 syslog adm  2087 Dec 24 06:25 /var/log/syslog.4.gz
-rw-r----- 1 syslog adm  2048 Dec 23 06:25 /var/log/syslog.5.gz
-rw-r----- 1 syslog adm  1499 Dec 22 06:25 /var/log/syslog.6.gz
-rw-r----- 1 syslog adm  2453 Dec 21 06:25 /var/log/syslog.7.gz

## サイズが1,625バイトのファイルを検索
$ find /var/log/ -name 'syslog.*' -size 1625c -ls
     7055      4 -rw-r-----   1 syslog   adm          1625 Dec 26 06:25 /var/log/syslog.2.gz

## サイズが2,000バイトより大きいファイルを検索
$ find /var/log/ -name 'syslog.*' -size +2000c -ls
     7012      4 -rw-r-----   1 syslog   adm          2048 Dec 23 06:25 /var/log/syslog.5.gz
     6306     24 -rw-r-----   1 syslog   adm         18401 Dec 27 06:25 /var/log/syslog.1
     7078      4 -rw-r-----   1 syslog   adm          2453 Dec 21 06:25 /var/log/syslog.7.gz
     7043      4 -rw-r-----   1 syslog   adm          2087 Dec 24 06:25 /var/log/syslog.4.gz

## サイズが2キビバイトより大きいファイルを検索
$ find /var/log/ -name 'syslog.*' -size +2k -ls
     6306     24 -rw-r-----   1 syslog   adm         18401 Dec 27 06:25 /var/log/syslog.1
     7078      4 -rw-r-----   1 syslog   adm          2453 Dec 21 06:25 /var/log/syslog.7.gz
     7043      4 -rw-r-----   1 syslog   adm          2087 Dec 24 06:25 /var/log/syslog.4.gz

## サイズが2キビバイトのファイルを検索
$ find /var/log/ -name 'syslog.*' -size 2k -ls
     7012      4 -rw-r-----   1 syslog   adm          2048 Dec 23 06:25 /var/log/syslog.5.gz
     7014      4 -rw-r-----   1 syslog   adm          1499 Dec 22 06:25 /var/log/syslog.6.gz
     7055      4 -rw-r-----   1 syslog   adm          1625 Dec 26 06:25 /var/log/syslog.2.gz
     7049      4 -rw-r-----   1 syslog   adm          1618 Dec 25 06:25 /var/log/syslog.3.gz
### 単位を指定した場合は単位以下の数字が切り上げられるため、
### 1キビバイトを超えるサイズのファイルは2キビバイトとなる

## サイズが2キビバイト未満のファイルを検索
$ find /var/log/ -name 'syslog.*' -size -2k -ls
## 単位以下の数字が切り上げられるため、該当なしとなることに注意

# -empty 空のファイルもしくはディレクトリを検索
$ find /var/log -empty -ls
    16133      0 -rw-r--r--   1 root     root            0 Dec 12 13:27 /var/log/landscape/sysinfo.log
     7088      0 -rw-r-----   1 syslog   adm             0 Dec 22 06:25 /var/log/kern.log
    80414      4 drwxr-xr-x   2 root     root         4096 Nov 23  2018 /var/log/lxd
    80412      4 drwxr-xr-x   2 root     root         4096 Jun 19  2019 /var/log/dist-upgrade
```

<details><summary>manページ記載の全検査</summary><div>

```
   TESTS
       Some tests, for example -newerXY and -samefile, allow comparison between the file currently being examined and some reference file
       specified on the command line.  When these tests are used, the interpretation of the reference file is determined by  the  options
       -H,  -L and -P and any previous -follow, but the reference file is only examined once, at the time the command line is parsed.  If
       the reference file cannot be examined (for example, the stat(2) system call fails for it), an error message is  issued,  and  find
       exits with a nonzero status.

       Numeric arguments can be specified as

       +n     for greater than n,

       -n     for less than n,

       n      for exactly n.

       -amin n
              File was last accessed n minutes ago.

       -anewer file
              File was last accessed more recently than file was modified.  If file is a symbolic link and the -H option or the -L option
              is in effect, the access time of the file it points to is always used.

       -atime n
              File was last accessed n*24 hours ago.  When find figures out how many 24-hour periods ago the file was last accessed,  any
              fractional part is ignored, so to match -atime +1, a file has to have been accessed at least two days ago.

       -cmin n
              File's status was last changed n minutes ago.

       -cnewer file
              File's  status  was last changed more recently than file was modified.  If file is a symbolic link and the -H option or the
              -L option is in effect, the status-change time of the file it points to is always used.

       -ctime n
              File's status was last changed n*24 hours ago.  See the comments for -atime to understand how rounding affects  the  inter‐
              pretation of file status change times.

       -empty File is empty and is either a regular file or a directory.

       -executable
              Matches files which are executable and directories which are searchable (in a file name resolution sense).  This takes into
              account access control lists and other permissions artefacts which the -perm test ignores.  This  test  makes  use  of  the
              access(2)  system  call,  and  so can be fooled by NFS servers which do UID mapping (or root-squashing), since many systems
              implement access(2) in the client's kernel and so cannot make use of the  UID  mapping  information  held  on  the  server.
              Because  this  test  is  based only on the result of the access(2) system call, there is no guarantee that a file for which
              this test succeeds can actually be executed.

       -false Always false.

       -fstype type
              File is on a filesystem of type type.  The valid filesystem types vary among different versions of Unix; an incomplete list
              of filesystem types that are accepted on some version of Unix or another is: ufs, 4.2, 4.3, nfs, tmp, mfs, S51K, S52K.  You
              can use -printf with the %F directive to see the types of your filesystems.

       -gid n File's numeric group ID is n.

       -group gname
              File belongs to group gname (numeric group ID allowed).

       -ilname pattern
              Like -lname, but the match is case insensitive.  If the -L option or the -follow option is in  effect,  this  test  returns
              false unless the symbolic link is broken.

       -iname pattern
              Like  -name,  but  the  match  is  case insensitive.  For example, the patterns `fo*' and `F??' match the file names `Foo',
              `FOO', `foo', `fOo', etc.   The pattern `*foo*` will also match a file called '.foobar'.

       -inum n
              File has inode number n.  It is normally easier to use the -samefile test instead.

       -ipath pattern
              Like -path.  but the match is case insensitive.

       -iregex pattern
              Like -regex, but the match is case insensitive.

       -iwholename pattern
              See -ipath.  This alternative is less portable than -ipath.

       -links n
              File has n hard links.

       -lname pattern
              File is a symbolic link whose contents match shell pattern pattern.  The metacharacters do not treat `/' or `.'  specially.
              If the -L option or the -follow option is in effect, this test returns false unless the symbolic link is broken.

       -mmin n
              File's data was last modified n minutes ago.

       -mtime n
              File's data was last modified n*24 hours ago.  See the comments for -atime to understand how rounding affects the interpre‐
              tation of file modification times.

       -name pattern
              Base of file name (the path with the leading directories removed) matches  shell  pattern  pattern.   Because  the  leading
              directories  are  removed, the file names considered for a match with -name will never include a slash, so `-name a/b' will
              never match anything (you probably need to use -path instead).  A warning is issued if you try to do this, unless the envi‐
              ronment variable POSIXLY_CORRECT is set.  The metacharacters (`*', `?', and `[]') match a `.' at the start of the base name
              (this is a change in findutils-4.2.2; see section STANDARDS CONFORMANCE below).  To ignore a directory and the files  under
              it,  use  -prune; see an example in the description of -path.  Braces are not recognised as being special, despite the fact
              that some shells including Bash imbue braces with a special meaning in shell patterns.  The filename matching is  performed
              with  the  use  of  the fnmatch(3) library function.   Don't forget to enclose the pattern in quotes in order to protect it
              from expansion by the shell.

       -newer file
              File was modified more recently than file.  If file is a symbolic link and the -H option or the -L option is in effect, the
              modification time of the file it points to is always used.

       -newerXY reference
              Succeeds if timestamp X of the file being considered is newer than timestamp Y of the file reference.   The letters X and Y
              can be any of the following letters:

              a   The access time of the file reference
              B   The birth time of the file reference
              c   The inode status change time of reference
              m   The modification time of the file reference
              t   reference is interpreted directly as a time

              Some combinations are invalid; for example, it is invalid for X to be t.  Some combinations are not implemented on all sys‐
              tems;  for example B is not supported on all systems.  If an invalid or unsupported combination of XY is specified, a fatal
              error results.  Time specifications are interpreted as for the argument to the -d option of GNU date.  If you  try  to  use
              the birth time of a reference file, and the birth time cannot be determined, a fatal error message results.  If you specify
              a test which refers to the birth time of files being examined, this test will fail for any files where the  birth  time  is
              unknown.

       -nogroup
              No group corresponds to file's numeric group ID.

       -nouser
              No user corresponds to file's numeric user ID.

       -path pattern
              File name matches shell pattern pattern.  The metacharacters do not treat `/' or `.' specially; so, for example,
                        find . -path "./sr*sc"
              will  print  an  entry  for  a directory called `./src/misc' (if one exists).  To ignore a whole directory tree, use -prune
              rather than checking every file in the tree.  For example, to skip the directory `src/emacs' and all files and  directories
              under it, and print the names of the other files found, do something like this:
                        find . -path ./src/emacs -prune -o -print
              Note that the pattern match test applies to the whole file name, starting from one of the start points named on the command
              line.  It would only make sense to use an absolute path name here if the relevant start point is  also  an  absolute  path.
              This means that this command will never match anything:
                        find bar -path /foo/bar/myfile -print
              Find  compares  the -path argument with the concatenation of a directory name and the base name of the file it's examining.
              Since the concatenation will never end with a slash, -path arguments ending in a slash will match nothing (except perhaps a
              start  point  specified on the command line).  The predicate -path is also supported by HP-UX find and is part of the POSIX
              2008 standard.

       -perm mode
              File's permission bits are exactly mode (octal or symbolic).  Since an exact match is required, if you  want  to  use  this
              form  for  symbolic  modes,  you may have to specify a rather complex mode string.  For example `-perm g=w' will only match
              files which have mode 0020 (that is, ones for which group write permission is the only permission set).  It is more  likely
              that  you  will want to use the `/' or `-' forms, for example `-perm -g=w', which matches any file with group write permis‐
              sion.  See the EXAMPLES section for some illustrative examples.

       -perm -mode
              All of the permission bits mode are set for the file.  Symbolic modes are accepted in this form, and this  is  usually  the
              way  in  which you would want to use them.  You must specify `u', `g' or `o' if you use a symbolic mode.   See the EXAMPLES
              section for some illustrative examples.

       -perm /mode
              Any of the permission bits mode are set for the file.  Symbolic modes are accepted in this form.  You must specify `u', `g'
              or `o' if you use a symbolic mode.  See the EXAMPLES section for some illustrative examples.  If no permission bits in mode
              are set, this test matches any file (the idea here is to be consistent with the behaviour of -perm -000).

       -perm +mode
              This is no longer supported (and has been deprecated since 2005).  Use -perm /mode instead.

       -readable
              Matches files which are readable.  This takes into account access control lists and other permissions artefacts  which  the
              -perm  test  ignores.   This  test makes use of the access(2) system call, and so can be fooled by NFS servers which do UID
              mapping (or root-squashing), since many systems implement access(2) in the client's kernel and so cannot make  use  of  the
              UID mapping information held on the server.

       -regex pattern
              File  name  matches  regular expression pattern.  This is a match on the whole path, not a search.  For example, to match a
              file named `./fubar3', you can use the regular expression `.*bar.' or `.*b.*3', but not `f.*r3'.  The  regular  expressions
              understood by find are by default Emacs Regular Expressions, but this can be changed with the -regextype option.

       -samefile name
              File refers to the same inode as name.   When -L is in effect, this can include symbolic links.

       -size n[cwbkMG]
              File uses n units of space, rounding up.  The following suffixes can be used:

              `b'    for 512-byte blocks (this is the default if no suffix is used)

              `c'    for bytes

              `w'    for two-byte words

              `k'    for Kibibytes (KiB, units of 1024 bytes)

              `M'    for Mebibytes (MiB, units of 1024 * 1024 = 1048576 bytes)

              `G'    for Gibibytes (GiB, units of 1024 * 1024 * 1024 = 1073741824 bytes)

              The size does not count indirect blocks, but it does count blocks in sparse files that are not actually allocated.  Bear in
              mind that the `%k' and `%b' format specifiers of -printf handle sparse files differently.  The `b'  suffix  always  denotes
              512-byte blocks and never 1024-byte blocks, which is different to the behaviour of -ls.

              The  + and - prefixes signify greater than and less than, as usual; i.e., an exact size of n units does not match.  Bear in
              mind that the size is rounded up to the next unit. Therefore -size -1M is not equivalent to -size  -1048576c.   The  former
              only matches empty files, the latter matches files from 0 to 1,048,575 bytes.

       -true  Always true.

       -type c
              File is of type c:

              b      block (buffered) special

              c      character (unbuffered) special

              d      directory

              p      named pipe (FIFO)

              f      regular file

              l      symbolic  link;  this is never true if the -L option or the -follow option is in effect, unless the symbolic link is
                     broken.  If you want to search for symbolic links when -L is in effect, use -xtype.

              s      socket

              D      door (Solaris)

              To search for more than one type at once, you can supply the combined list of type letters separated by a  comma  `,'  (GNU
              extension).

       -uid n File's numeric user ID is n.

       -used n
              File was last accessed n days after its status was last changed.

       -user uname
              File is owned by user uname (numeric user ID allowed).

       -wholename pattern
              See -path.  This alternative is less portable than -path.

       -writable
              Matches  files  which are writable.  This takes into account access control lists and other permissions artefacts which the
              -perm test ignores.  This test makes use of the access(2) system call, and so can be fooled by NFS  servers  which  do  UID
              mapping  (or  root-squashing),  since many systems implement access(2) in the client's kernel and so cannot make use of the
              UID mapping information held on the server.

       -xtype c
              The same as -type unless the file is a symbolic link.  For symbolic links: if the -H or -P option was  specified,  true  if
              the  file  is  a link to a file of type c; if the -L option has been given, true if c is `l'.  In other words, for symbolic
              links, -xtype checks the type of the file that -type does not check.

       -context pattern
              (SELinux only) Security context of the file matches glob pattern.
```

</div></details>

下記のようなオプションもある。
`-user`ファイルのユーザー名で検索（ユーザーID指定も可能）
`-group`ファイルのグループ名で検索（グループID指定も可能）
`-nouser`ファイルのユーザーIDに対応するユーザーがいないファイルを検索
`-nogroup`ファイルのグループIDに対応するグループがいないファイルを検索
`-context`SELinuxのセキュリティコンテキストを検索

### アクション

findコマンドの仕上げ。
コマンドなどを実行するアクションの指定。
主に下記のようなことが可能。

* 任意のコマンドを1ファイルにつき1コマンドで実行
* 任意のコマンドを複数ファイルに対してまとめて実行
* ファイルリストをロングフォーマットや任意のフォーマットで表示
* ファイルを削除

任意のコマンド実行には`-exec`を使う。
`-exec`コマンドを実行するときは
`$ find -type f -exec ls -l '{}' \;`
のような感じで指定する。
{}にfindで見つかったファイルが展開される。
シェル展開されないように、{}や;はエスケープが必要。{}と;の間の空白は必須。
任意のコマンドを1ファイルにつき1コマンドで実行する場合は、最後に;を付ける。
任意のコマンドを複数ファイルに対してまとめて実行する場合は、最後に+を付ける。

`-exec`で何でもできてしまうが、ファイルリスト表示やファイル削除などのよく使いそうなものは専用のコマンドが用意されている。

```shell
# -exec command ; 任意のコマンドを1ファイルにつき1コマンドで実行
# -exec command + 任意のコマンドを複数ファイルに対してまとめて実行

## ファイルのみを検索してlsコマンドを実行
$ find -type f -exec ls -l '{}' \;
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 27 15:06 ./piyo.txt
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 27 15:06 ./hoge.txt
## コマンドはfindを実行したディレクトリで実行される
## コマンドをファイルが存在するディレクトリで実行したい場合は-execdirを使う

## ;指定の場合は、1ファイルにつき1コマンドが実行される
$ find -type f -exec echo 'echoコマンド実行' '{}' \;
echoコマンド実行 ./piyo.txt
echoコマンド実行 ./hoge.txt

## +指定の場合は、（可能な限り）1回のコマンド実行にまとめられる
$ find -type f -exec echo 'echoコマンド実行' '{}' \+
echoコマンド実行 ./piyo.txt ./hoge.txt
## こっちのほうがパフォーマンスがいいので、通常は+での実行がおすすめ

# -ok ’-exec’コマンドとほぼ同じだが、コマンド実行前に確認メッセージを表示する
$ find -type f -ok ls -l '{}' \;
< ls ... ./piyo.txt > ? y
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 27 15:06 ./piyo.txt
< ls ... ./hoge.txt > ? y
-rw-rw-r-- 1 ubuntu ubuntu 0 Dec 27 15:06 ./hoge.txt
## コマンドをファイルが存在するディレクトリで実行したい場合は-okdirを使う

# -ls ファイルリストを表示する
$ find -type f -ls
   256220      0 -rw-rw-r--   1 ubuntu   ubuntu          0 Dec 27 15:06 ./piyo.txt
   256216      0 -rw-rw-r--   1 ubuntu   ubuntu          0 Dec 27 15:06 ./hoge.txt
## lsのロングフォーマットの情報に加えて、inodeとブロックサイズの情報を表示する
## -flsを代わりに使用することで、結果をファイルに格納することも可能

# -delete ファイルを削除
## 下記階層のディレクトリを例に説明
$ tree
.
├── hoge
│   └── hogehoge.txt
├── hoge.txt
├── piyo
│   └── piyopiyo.txt
└── piyo.txt

## -deleteは条件に合致するファイルを警告なしで全て消すので、
## 事前に-deleteなしで削除されるファイルを確認したほうがいい
$ find -depth -name 'hoge*'
./hoge/hogehoge.txt
./hoge
./hoge.txt
## -deleteはディレクトリの中身を消してからディレクトリ自体を削除する動作をするため、
## -depthオプションが暗黙的に指定される
## 削除されるファイルの順番も合わせて確認するために、
## 事前確認時も-depthオプションを付けるのがおすすめ

## ファイルの削除
$ find -depth -name 'hoge*' -delete
## メッセージは何も表示されない

## ファイルは削除されている
$ tree
.
├── piyo
│   └── piyopiyo.txt
└── piyo.txt

# -print ファイルリストを表示する（アクション省略時のデフォルト動作）
$ find -type f -print
./piyo.txt
./hoge.txt

# -print0 ファイルリストをnull文字（¥0）区切りで表示する
$ find -type f -print0
./piyo.txt./hoge.txt
## 空白や制御文字を含むファイル名があると、-printを使ってもうまくパイプで別コマンドに渡せない
## そのような場合に-print0を使用する

# -prune 指定したディレクトリ以下を検索対象外とする
## 下記階層のディレクトリを例に説明
$ tree
.
├── hoge
│   ├── hogehoge
│   │   └── hogehogehoge.txt
│   └── hogehoge.txt
└── piyo
    ├── piyopiyo
    │   └── piyopiyopiyo.txt
    └── piyopiyo.txt

## -pruneを指定しない場合
$ find -type f -print
./piyo/piyopiyo/piyopiyopiyo.txt
./piyo/piyopiyo.txt
./hoge/hogehoge.txt
./hoge/hogehoge/hogehogehoge.txt

## -pruneを指定した場合
$ find -name 'hoge' -prune -or -type f -print
./piyo/piyopiyo/piyopiyopiyo.txt
./piyo/piyopiyo.txt
### hogeディレクトリ配下を検索対象外にできる
```

<details><summary>manページ記載の全アクション</summary><div>

```
   ACTIONS
       -delete
              Delete files; true if removal succeeded.  If the removal failed, an error message is issued.  If -delete fails, find's exit
              status will be nonzero (when it eventually exits).  Use of -delete automatically turns on the `-depth' option.

              Warnings:  Don't  forget  that the find command line is evaluated as an expression, so putting -delete first will make find
              try to delete everything below the starting points you specified.  When testing a find command line that you  later  intend
              to  use  with  -delete,  you  should  explicitly specify -depth in order to avoid later surprises.  Because -delete implies
              -depth, you cannot usefully use -prune and -delete together.

       -exec command ;
              Execute command; true if 0 status is returned.  All following arguments to find are taken to be arguments  to  the  command
              until  an  argument consisting of `;' is encountered.  The string `{}' is replaced by the current file name being processed
              everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find.
              Both  of  these  constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell.
              See the EXAMPLES section for examples of the use of the -exec option.  The specified command is run once for  each  matched
              file.   The command is executed in the starting directory.   There are unavoidable security problems surrounding use of the
              -exec action; you should use the -execdir option instead.

       -exec command {} +
              This variant of the -exec action runs the specified command on the selected files, but the command line is built by append‐
              ing each selected file name at the end; the total number of invocations of the command will be much less than the number of
              matched files.  The command line is built in much the same way that xargs builds its command lines.  Only one  instance  of
              `{}'  is  allowed within the command, and (when find is being invoked from a shell) it should be quoted (for example, '{}')
              to protect it from interpretation by shells.  The command is executed in the starting directory.  If any invocation returns
              a non-zero value as exit status, then find returns a non-zero exit status.  If find encounters an error, this can sometimes
              cause an immediate exit, so some pending commands may not be run at all.  This variant of -exec always returns true.

       -execdir command ;

       -execdir command {} +
              Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not  normally  the
              directory in which you started find.  As with -exec, the {} should be quoted if find is being invoked from a shell.  This a
              much more secure method for invoking commands, as it avoids race conditions during resolution of the paths to  the  matched
              files.  As with the -exec action, the `+' form of -execdir will build a command line to process more than one matched file,
              but any given invocation of command will only list files that exist in the same subdirectory.  If you use this option,  you
              must  ensure  that your $PATH environment variable does not reference `.'; otherwise, an attacker can run any commands they
              like by leaving an appropriately-named file in a directory in which you will run -execdir.   The  same  applies  to  having
              entries  in $PATH which are empty or which are not absolute directory names.  If any invocation returns a non-zero value as
              exit status, then find returns a non-zero exit status.  If find encounters an error, this can sometimes cause an  immediate
              exit, so some pending commands may not be run at all. The result of the action depends on whether the + or the ; variant is
              being used; -execdir command {} + always returns true, while -execdir command {} ; returns true only if command returns 0.

       -fls file
              True; like -ls but write to file like -fprint.  The output file is always created, even if the predicate is never  matched.
              See the UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled.

       -fprint file
              True;  print  the full file name into file file.  If file does not exist when find is run, it is created; if it does exist,
              it is truncated.  The file names `/dev/stdout' and `/dev/stderr' are handled specially; they refer to the  standard  output
              and  standard  error output, respectively.  The output file is always created, even if the predicate is never matched.  See
              the UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled.

       -fprint0 file
              True; like -print0 but write to file like -fprint.  The output file is always created,  even  if  the  predicate  is  never
              matched.  See the UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled.

       -fprintf file format
              True;  like  -printf  but  write  to  file like -fprint.  The output file is always created, even if the predicate is never
              matched.  See the UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled.

       -ls    True; list current file in ls -dils format on standard output.  The block counts are of 1K blocks, unless  the  environment
              variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.  See the UNUSUAL FILENAMES section for information
              about how unusual characters in filenames are handled.

       -ok command ;
              Like -exec but ask the user first.  If the user agrees, run the command.  Otherwise just return false.  If the  command  is
              run, its standard input is redirected from /dev/null.

              The  response  to the prompt is matched against a pair of regular expressions to determine if it is an affirmative or nega‐
              tive response.  This regular expression is obtained from the system if the `POSIXLY_CORRECT' environment variable  is  set,
              or  otherwise  from  find's  message translations.  If the system has no suitable definition, find's own definition will be
              used.   In either case, the interpretation of the regular expression itself will be affected by the  environment  variables
              'LC_CTYPE' (character classes) and 'LC_COLLATE' (character ranges and equivalence classes).

       -okdir command ;
              Like  -execdir  but  ask the user first in the same way as for -ok.  If the user does not agree, just return false.  If the
              command is run, its standard input is redirected from /dev/null.

       -print True; print the full file name on the standard output, followed by a newline.   If you are piping the output of  find  into
              another  program  and there is the faintest possibility that the files which you are searching for might contain a newline,
              then you should seriously consider using the -print0 option instead of -print.   See  the  UNUSUAL  FILENAMES  section  for
              information about how unusual characters in filenames are handled.

       -print0
              True;  print the full file name on the standard output, followed by a null character (instead of the newline character that
              -print uses).  This allows file names that contain newlines or other types of white space to be  correctly  interpreted  by
              programs that process the find output.  This option corresponds to the -0 option of xargs.

       -printf format
              True; print format on the standard output, interpreting `\' escapes and `%' directives.  Field widths and precisions can be
              specified as with the `printf' C function.  Please note that many of the fields are printed as %s rather than %d, and  this
              may  mean  that  flags don't work as you might expect.  This also means that the `-' flag does work (it forces fields to be
              left-aligned).  Unlike -print, -printf does not add a newline at the end of the string.  The escapes and directives are:

              \a     Alarm bell.

              \b     Backspace.

              \c     Stop printing from this format immediately and flush the output.

              \f     Form feed.

              \n     Newline.

              \r     Carriage return.

              \t     Horizontal tab.

              \v     Vertical tab.

              \0     ASCII NUL.

              \\     A literal backslash (`\').

              \NNN   The character whose ASCII code is NNN (octal).

              A `\' character followed by any other character is treated as an ordinary character, so they both are printed.

              %%     A literal percent sign.

              %a     File's last access time in the format returned by the C `ctime' function.

              %Ak    File's last access time in the format specified by k, which is either `@' or a directive for the C `strftime'  func‐
                     tion.   The  possible values for k are listed below; some of them might not be available on all systems, due to dif‐
                     ferences in `strftime' between systems.

                     @      seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.

                     Time fields:

                     H      hour (00..23)

                     I      hour (01..12)

                     k      hour ( 0..23)

                     l      hour ( 1..12)

                     M      minute (00..59)

                     p      locale's AM or PM

                     r      time, 12-hour (hh:mm:ss [AP]M)

                     S      Second (00.00 .. 61.00).  There is a fractional part.

                     T      time, 24-hour (hh:mm:ss.xxxxxxxxxx)

                     +      Date and time, separated by `+', for example `2004-04-28+22:22:05.0'.  This is a GNU extension.  The time  is
                            given  in  the  current timezone (which may be affected by setting the TZ environment variable).  The seconds
                            field includes a fractional part.

                     X      locale's time representation (H:M:S).  The seconds field includes a fractional part.

                     Z      time zone (e.g., EDT), or nothing if no time zone is determinable

                     Date fields:

                     a      locale's abbreviated weekday name (Sun..Sat)

                     A      locale's full weekday name, variable length (Sunday..Saturday)

                     b      locale's abbreviated month name (Jan..Dec)

                     B      locale's full month name, variable length (January..December)

                     c      locale's date and time (Sat Nov 04 12:02:33 EST 1989).  The format is the same as for ctime(3) and so to pre‐
                            serve compatibility with that format, there is no fractional part in the seconds field.

                     d      day of month (01..31)

                     D      date (mm/dd/yy)

                     h      same as b

                     j      day of year (001..366)

                     m      month (01..12)

                     U      week number of year with Sunday as first day of week (00..53)

                     w      day of week (0..6)

                     W      week number of year with Monday as first day of week (00..53)

                     x      locale's date representation (mm/dd/yy)

                     y      last two digits of year (00..99)

                     Y      year (1970...)

              %b     The  amount  of disk space used for this file in 512-byte blocks.  Since disk space is allocated in multiples of the
                     filesystem block size this is usually greater than %s/512, but it can also be smaller if the file is a sparse file.

              %c     File's last status change time in the format returned by the C `ctime' function.

              %Ck    File's last status change time in the format specified by k, which is the same as for %A.

              %d     File's depth in the directory tree; 0 means the file is a starting-point.

              %D     The device number on which the file exists (the st_dev field of struct stat), in decimal.

              %f     File's name with any leading directories removed (only the last element).

              %F     Type of the filesystem the file is on; this value can be used for -fstype.

              %g     File's group name, or numeric group ID if the group has no name.

              %G     File's numeric group ID.

              %h     Leading directories of file's name (all but the last element).  If the file name contains no slashes (since it is in
                     the current directory) the %h specifier expands to `.'.

              %H     Starting-point under which file was found.

              %i     File's inode number (in decimal).

              %k     The  amount  of  disk  space  used  for  this  file in 1K blocks.  Since disk space is allocated in multiples of the
                     filesystem block size this is usually greater than %s/1024, but it can also be smaller if the file is a sparse file.

              %l     Object of symbolic link (empty string if file is not a symbolic link).

              %m     File's permission bits (in octal).  This option uses the `traditional' numbers which most Unix implementations  use,
                     but  if your particular implementation uses an unusual ordering of octal permissions bits, you will see a difference
                     between the actual value of the file's mode and the output of %m.   Normally you will want to have a leading zero on
                     this number, and to do this, you should use the # flag (as in, for example, `%#m').

              %M     File's permissions (in symbolic form, as for ls).  This directive is supported in findutils 4.2.5 and later.

              %n     Number of hard links to file.

              %p     File's name.

              %P     File's name with the name of the starting-point under which it was found removed.

              %s     File's size in bytes.

              %S     File's  sparseness.   This  is  calculated  as (BLOCKSIZE*st_blocks / st_size).  The exact value you will get for an
                     ordinary file of a certain length is system-dependent.  However, normally sparse files will have  values  less  than
                     1.0,  and files which use indirect blocks may have a value which is greater than 1.0.   The value used for BLOCKSIZE
                     is system-dependent, but is usually 512 bytes.   If the file size is zero, the value printed is undefined.  On  sys‐
                     tems which lack support for st_blocks, a file's sparseness is assumed to be 1.0.

              %t     File's last modification time in the format returned by the C `ctime' function.

              %Tk    File's last modification time in the format specified by k, which is the same as for %A.

              %u     File's user name, or numeric user ID if the user has no name.

              %U     File's numeric user ID.

              %y     File's type (like in ls -l), U=unknown type (shouldn't happen)

              %Y     File's type (like %y), plus follow symlinks: L=loop, N=nonexistent

              %Z     (SELinux only) file's security context.

              %{ %[ %(
                     Reserved for future use.

              A  `%'  character  followed by any other character is discarded, but the other character is printed (don't rely on this, as
              further format characters may be introduced).  A `%' at the end of the format argument  causes  undefined  behaviour  since
              there is no following character.  In some locales, it may hide your door keys, while in others it may remove the final page
              from the novel you are reading.

              The %m and %d directives support the # , 0 and + flags, but the other directives  do  not,  even  if  they  print  numbers.
              Numeric  directives  that  do  not  support  these flags include G, U, b, D, k and n.  The `-' format flag is supported and
              changes the alignment of a field from right-justified (which is the default) to left-justified.

              See the UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled.

       -prune True; if the file is a directory, do not descend into it.  If -depth is given, false; no effect.  Because  -delete  implies
              -depth, you cannot usefully use -prune and -delete together.

       -quit  Exit  immediately.   No  child processes will be left running, but no more paths specified on the command line will be pro‐
              cessed.  For example, find /tmp/foo /tmp/bar -print -quit will print only /tmp/foo.  Any  command  lines  which  have  been
              built  up  with -execdir ... {} + will be invoked before find exits.   The exit status may or may not be zero, depending on
              whether an error has already occurred.
```

</div></details>

下記のようなオプションもある。
`-printf`出力フォーマットを指定してファイルリストを出力する

## コマンド解説③ grepコマンド
```
$ whatis grep
grep (1)             - print lines matching a pattern
```
ファイルの中身から、パターンにマッチする文字列を検索するコマンド。
検証バージョンはこちら。

```
$ grep --version
grep (GNU grep) 3.1
```

### 基本的な使い方

```shell
# 指定したファイルから、パターンにマッチする文字列を検索
$ grep -E 'dependency.*javax' spring-framework/build.gradle 
			dependency "com.sun.activation:javax.activation:1.2.0"
			dependency "com.sun.mail:javax.mail:1.6.2"
			dependency "javax.activation:javax.activation-api:1.2.0"
			dependency "javax.annotation:javax.annotation-api:1.3.2"
・・・

# サブディレクトリ配下の全てのファイルから、パターンにマッチする文字列を検索
$ grep -E -r 'public interface' spring-framework/spring-core/src/main/java/
spring-framework/spring-core/src/main/java/org/springframework/asm/Opcodes.java:public interface Opcodes {
spring-framework/spring-core/src/main/java/org/springframework/util/MultiValueMap.java:public interface MultiValueMap<K, V> extends Map<K, List<V>> {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/FailureCallback.java:public interface FailureCallback {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFuture.java:public interface ListenableFuture<T> extends Future<T> {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallback.java:public interface ListenableFutureCallback<T> extends SuccessCallback<T>, FailureCallback {
・・・
```

### 全体を俯瞰してみる

grepコマンドで指定できるオプションは、大きく3種類。

1. 使用する正規表現タイプの指定
1. 検索方法の指定（大文字小文字を区別しない、単語で検索など）
1. 出力方法の指定（行番号の表示、ファイル名の表示など）

使い方も素直なので、あまり迷うところもない印象。

まずポイントとなるのは、正規表現タイプに拡張正規表現（ERE）、もしくはPerl正規表現を選ぶこと。
デフォルトの基本正規表現（BRE）より、表現力も書きやすさも格段にアップする。
他のコマンドでも使用できる汎用性を重視するなら拡張正規表現（ERE）、表現力を追求するならPerl正規表現を使いましょう。

あとは、サブディレクトリも対象にgrepを実行すると検索結果が大量に出ることが多いので、出力情報をオプションで適切に絞る方法を覚えると、効率的に結果を把握できる。

指定できるオプション数は全部で46個。

|カテゴリ|オプション数|備考|
|:-:|:-:|:-:|
|正規表現タイプ指定|4||
|検索方法指定|19||
|出力方法指定|21||
|その他|2|--helpと--version|

findの後だと、少なく見えてしまいますね。
どんどん見ていきましょう。

### 正規表現タイプ指定

検索に使用する正規表現タイプとして、下記のいずれかを指定できる。

* `-G` 基本正規表現（BRE）（デフォルト） 
* `-E` 拡張正規表現（ERE）
* `-P` Perl正規表現
* `-F` 正規表現を使用せずに固定文字列として検索

正規表現を使用する場合は、まずは拡張正規表現（ERE）を選んでおけば間違いない。
制御文字をそのまま検索したい場合は、固定文字列として検索するのが便利。

<details><summary>正規表現タイプ指定関連の全オプション</summary><div>

```
       -E, --extended-regexp
              Interpret PATTERN as an extended regular expression (ERE, see below).

       -F, --fixed-strings
              Interpret PATTERN as a list of fixed strings (instead of regular expressions), separated by newlines, any of which is to be
              matched.

       -G, --basic-regexp
              Interpret PATTERN as a basic regular expression (BRE, see below).  This is the default.

       -P, --perl-regexp
              Interpret the pattern as a Perl-compatible regular expression (PCRE).  This  is  experimental  and  grep  -P  may  warn  of
              unimplemented features.
```

</div></details>

`-E`や`-F`の代わりにegrepやfgrepというコマンドもあるが非推奨。

### 検索方法指定

主に下記のようなことを指定可能。

* 大文字小文字を区別しない
* 単語として検索
* サブディレクトリ配下の全てのファイルから検索
* 検索対象、検索対象外とするファイルの指定

```shell
# -i 大文字小文字を区別しない
$ cat hoge.txt
abc
ABC
Abc
$ grep 'abc' hoge.txt
abc
$ grep -i 'abc' hoge.txt
abc
ABC
Abc

# -w 単語単位で検索
$ cat hoge.txt
abcdefghi
abc def ghi
$ grep 'def' hoge.txt
abcdefghi
abc def ghi
$ grep -w 'def' hoge.txt
abc def ghi

# -x パターンと完全一致する行を検索
$ cat hoge.txt
abc
abcdef
def
defghi
$ grep 'def' hoge.txt
abcdef
def
defghi
$ grep -x 'def' hoge.txt
def

# -v パターンとマッチしない行を検索
$ cat hoge.txt
abc
def
ghi
$ grep 'abc' hoge.txt
abc
$ $ grep -v 'abc' hoge.txt
def
ghi

# -e 正規表現パターンを複数指定する。指定したパターンのいずれかに合致する行を表示
$ cat hoge.txt
abc
def
ghi
jkl
$ grep -e 'abc' -e 'ghi' hoge.txt
abc
ghi
## -fで、正規表現パターンをコマンドラインではなくファイルから指定することもできる

# -r サブディレクトリ配下の全てのファイルから、パターンにマッチする文字列を検索
## リンク先はコマンドラインで指定したもの以外は検索しない
$ grep -r 'public interface' spring-framework/spring-core/src/main/java/
spring-framework/spring-core/src/main/java/org/springframework/asm/Opcodes.java:public interface Opcodes {
spring-framework/spring-core/src/main/java/org/springframework/util/MultiValueMap.java:public interface MultiValueMap<K, V> extends Map<K, List<V>> {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/FailureCallback.java:public interface FailureCallback {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFuture.java:public interface ListenableFuture<T> extends Future<T> {
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallback.java:public interface ListenableFutureCallback<T> extends SuccessCallback<T>, FailureCallback {
・・・
## 全てのリンク先を検索したい場合は、-Rを使用する

# --exclude=GLOB 指定したファイルを検索対象外とする
# --exclude-dir=GLOB 指定したディレクトリを検索対象外とする
$ grep -r 'abc' .
./piyo/piyopiyo.txt:abc
./piyo.txt:abc
./hoge/hogehoge.txt:abc
./hoge.txt:abc
$ grep -r --exclude=piyo*.txt 'abc' .
./hoge/hogehoge.txt:abc
./hoge.txt:abc
$ grep -r --exclude-dir=piyo 'abc' .
./piyo.txt:abc
./hoge/hogehoge.txt:abc
./hoge.txt:abc
## --exclude-from=FILEで、検索対象外とするファイルを
## コマンドラインではなくファイルから指定することもできる

# --include=GLOB 指定したファイルのみを検索対象とする
$ grep -r 'abc' .
./piyo/piyopiyo.txt:abc
./piyo.txt:abc
./hoge/hogehoge.txt:abc
./hoge.txt:abc
$ grep -r --include=piyo*.txt 'abc' .
./piyo/piyopiyo.txt:abc
./piyo.txt:abc
```

<details><summary>検索方法指定関連の全オプション</summary><div>

```
       -e PATTERN, --regexp=PATTERN
              Use  PATTERN  as the pattern.  If this option is used multiple times or is combined with the -f (--file) option, search for
              all patterns given.  This option can be used to protect a pattern beginning with “-”.

       -f FILE, --file=FILE
              Obtain patterns from FILE, one per line.  If this option is used multiple times or  is  combined  with  the  -e  (--regexp)
              option, search for all patterns given.  The empty file contains zero patterns, and therefore matches nothing.

       -i, --ignore-case
              Ignore case distinctions, so that characters that differ only in case match each other.

       -v, --invert-match
              Invert the sense of matching, to select non-matching lines.

       -w, --word-regexp
              Select  only  those lines containing matches that form whole words.  The test is that the matching substring must either be
              at the beginning of the line, or preceded by a non-word constituent character.  Similarly, it must be either at the end  of
              the  line  or  followed  by  a  non-word  constituent  character.  Word-constituent characters are letters, digits, and the
              underscore.  This option has no effect if -x is also specified.

       -x, --line-regexp
              Select only those matches that exactly match the whole line.  For a regular expression pattern, this is like parenthesizing
              the pattern and then surrounding it with ^ and $.

       -y     Obsolete synonym for -i.

       -a, --text
              Process a binary file as if it were text; this is equivalent to the --binary-files=text option.

       --binary-files=TYPE
              If  a  file's data or metadata indicate that the file contains binary data, assume that the file is of type TYPE.  Non-text
              bytes indicate binary data; these are either output bytes that are improperly encoded for the current locale, or null input
              bytes when the -z option is not given.

              By  default,  TYPE  is  binary, and when grep discovers that a file is binary it suppresses any further output, and instead
              outputs either a one-line message saying that a binary file matches, or no message if there is no match.

              If TYPE is without-match, when grep discovers that a file is binary it assumes that the rest of the file  does  not  match;
              this is equivalent to the -I option.

              If TYPE is text, grep processes a binary file as if it were text; this is equivalent to the -a option.

              When  type  is  binary,  grep may treat non-text bytes as line terminators even without the -z option.  This means choosing
              binary versus text can affect whether a pattern matches a file.  For example, when type is  binary  the  pattern  q$  might
              match  q  immediately followed by a null byte, even though this is not matched when type is text.  Conversely, when type is
              binary the pattern . (period) might not match a null byte.

              Warning: The -a option might output binary garbage, which can have nasty side effects if the output is a  terminal  and  if
              the  terminal  driver  interprets  some  of it as commands.  On the other hand, when reading files whose text encodings are
              unknown, it can be helpful to use -a or to set LC_ALL='C' in the environment, in order to find more  matches  even  if  the
              matches are unsafe for direct display.

       -D ACTION, --devices=ACTION
              If  an  input  file  is  a  device, FIFO or socket, use ACTION to process it.  By default, ACTION is read, which means that
              devices are read just as if they were ordinary files.  If ACTION is skip, devices are silently skipped.

       -d ACTION, --directories=ACTION
              If an input file is a directory, use ACTION to process it.  By default, ACTION is read, i.e., read directories just  as  if
              they  were  ordinary files.  If ACTION is skip, silently skip directories.  If ACTION is recurse, read all files under each
              directory, recursively, following symbolic links only if they are on the command  line.   This  is  equivalent  to  the  -r
              option.

       --exclude=GLOB
              Skip  any  command-line  file  with  a name suffix that matches the pattern GLOB, using wildcard matching; a name suffix is
              either the whole name, or any suffix starting after a / and before a +non-/.  When searching recursively, skip any  subfile
              whose base name matches GLOB; the base name is the part after the last /.  A pattern can use *, ?, and [...]  as wildcards,
              and \ to quote a wildcard or backslash character literally.

       --exclude-from=FILE
              Skip files whose base name matches any of the file-name globs read from FILE (using wildcard matching  as  described  under
              --exclude).

       --exclude-dir=GLOB
              Skip  any  command-line  directory  with a name suffix that matches the pattern GLOB.  When searching recursively, skip any
              subdirectory whose base name matches GLOB.  Ignore any redundant trailing slashes in GLOB.

       -I     Process a binary file as if it did not contain matching  data;  this  is  equivalent  to  the  --binary-files=without-match
              option.

       --include=GLOB
              Search only files whose base name matches GLOB (using wildcard matching as described under --exclude).

       -r, --recursive
              Read all files under each directory, recursively, following symbolic links only if they are on the command line.  Note that
              if no file operand is given, grep searches the working directory.  This is equivalent to the -d recurse option.

       -R, --dereference-recursive
              Read all files under each directory, recursively.  Follow all symbolic links, unlike -r.

       -U, --binary
              Treat the file(s) as binary.  By default, under MS-DOS and MS-Windows, grep guesses whether a file is  text  or  binary  as
              described  for  the  --binary-files  option.  If grep decides the file is a text file, it strips the CR characters from the
              original file contents (to make regular expressions with ^ and $ work correctly).  Specifying -U overrules this  guesswork,
              causing  all files to be read and passed to the matching mechanism verbatim; if the file is a text file with CR/LF pairs at
              the end of each line, this will cause some regular expressions to fail.  This option has no effect on platforms other  than
              MS-DOS and MS-Windows.
```

</div></details>

`-a`で、バイナリファイルをテキストファイルとして検索することができる。テキストファイルがバイナリファイルだと誤判定される場合に便利。

### 出力方法指定

主に下記のようなことを指定可能。

* 行番号を表示
* ファイル名の表示
* マッチした行数のみ表示
* マッチしたファイル名のみ表示
* マッチした前後の行も合わせて表示
* マッチさせる行数の制限

```shell
# -n 行番号を表示する
# -n バイトオフセットを表示する
# -T 行番号と検索結果をタブで揃えて表示する
$ cat hoge.txt
aaa
bbb
ccc
ddd
eee
$ grep -E -n '[a|c|e]' hoge.txt
1:aaa
3:ccc
5:eee
$ grep -E -b '[a|c|e]' hoge.txt
0:aaa
8:ccc
16:eee
$ grep -E -bT '[a|c|e]' hoge.txt
 0:	aaa
 8:	ccc
16:	eee

# -c マッチした行数のみ表示する
$ cat hoge.txt
aaa
bbb
aaa
bbb
aaa
bbb
$ grep -c 'aaa' hoge.txt
3

# -H 検索結果と合わせてファイル名も表示する（複数ファイル検索時のデフォルト）
# -h 検索結果にファイル名を表示しない（単一ファイル検索時のデフォルト）
$ cat hoge.txt
abc
$ cat piyo.txt
abc

## 単一ファイル検索
$ grep 'abc' hoge.txt
abc
$ grep -H 'abc' hoge.txt
hoge.txt:abc

## 複数ファイル検索
$ grep 'abc' hoge.txt piyo.txt
hoge.txt:abc
piyo.txt:abc
$ grep -h 'abc' hoge.txt piyo.txt
abc
abc

# -l マッチしたファイル名のみ表示する
$ grep -lr 'public interface' spring-framework/spring-core/src/main/java/
spring-framework/spring-core/src/main/java/org/springframework/asm/Opcodes.java
spring-framework/spring-core/src/main/java/org/springframework/util/MultiValueMap.java
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/FailureCallback.java
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFuture.java
spring-framework/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallback.java
・・・

# -L マッチしなかったファイル名のみ表示する
$ grep -Lr 'public interface' spring-framework/spring-core/src/main/java/
spring-framework/spring-core/src/main/java/org/springframework/asm/ClassWriter.java
spring-framework/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java
spring-framework/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java
spring-framework/spring-core/src/main/java/org/springframework/asm/Label.java
spring-framework/spring-core/src/main/java/org/springframework/asm/ModuleWriter.java
・・・

# -o マッチした部分だけを表示する
$ cat hoge.txt
abcdefghi
defghijkl
$ grep -E 'g.*' hoge.txt
abcdefghi
defghijkl
$ grep -E -o 'g.*' hoge.txt
ghi
ghijkl

# -B NUM マッチした行の前の行をNUMで指定した行数分表示する
# -A NUM マッチした行の後の行をNUMで指定した行数分表示する
# -C NUM マッチした行の前後の行をNUMで指定した行数分表示する（-NUMでも可）
$ cat hoge.txt
a
b
c
d
e
f
g

$ grep -B 2 'd' hoge.txt
b
c
d

$ grep -A 2 'd' hoge.txt
d
e
f

$ grep -C 2 'd' hoge.txt
b
c
d
e
f

$ grep -2 'd' hoge.txt
b
c
d
e
f
## ハイフンと数字のみの指定でも前後の行を表示できる

# -m NUM マッチさせる行数を制限する
$ cat hoge.txt
abc
def
abc
def
abc
def

## -mを指定しない場合
$ grep -n 'abc' hoge.txt
1:abc
3:abc
5:abc
## 全ての一致箇所が表示される

## -mを指定をした場合
$ grep -n -m 2 'abc' hoge.txt
1:abc
3:abc
## 指定した行数分しか検索しない

# -s エラーメッセージを表示しない
$ tree
.
├── hoge
├── hoge.txt
├── piyo
└── piyo.txt

## -sを指定しない場合
$ grep 'abc' *
grep: hoge: Is a directory
hoge.txt:abc
grep: piyo: Is a directory
piyo.txt:abc
## ディレクトリを検索するとエラーメッセージが表示される

## -sを指定した場合
$ grep -s 'abc' *
hoge.txt:abc
piyo.txt:abc
## エラーメッセージは表示されない
```

<details><summary>出力方法指定関連の全オプション</summary><div>

```
       -c, --count
              Suppress  normal  output;  instead print a count of matching lines for each input file.  With the -v, --invert-match option
              (see below), count non-matching lines.

       --color[=WHEN], --colour[=WHEN]
              Surround the matched (non-empty) strings, matching lines, context lines,  file  names,  line  numbers,  byte  offsets,  and
              separators  (for  fields  and groups of context lines) with escape sequences to display them in color on the terminal.  The
              colors are defined by the environment variable GREP_COLORS.   The  deprecated  environment  variable  GREP_COLOR  is  still
              supported, but its setting does not have priority.  WHEN is never, always, or auto.

       -L, --files-without-match
              Suppress  normal  output;  instead print the name of each input file from which no output would normally have been printed.
              The scanning will stop on the first match.

       -l, --files-with-matches
              Suppress normal output; instead print the name of each input file from which output would normally have been printed.   The
              scanning will stop on the first match.

       -m NUM, --max-count=NUM
              Stop  reading  a file after NUM matching lines.  If the input is standard input from a regular file, and NUM matching lines
              are output, grep ensures that the standard input is positioned to  just  after  the  last  matching  line  before  exiting,
              regardless  of the presence of trailing context lines.  This enables a calling process to resume a search.  When grep stops
              after NUM matching lines, it outputs any trailing context lines.  When the -c or --count option is also used, grep does not
              output  a  count greater than NUM.  When the -v or --invert-match option is also used, grep stops after outputting NUM non-
              matching lines.

       -o, --only-matching
              Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

       -q, --quiet, --silent
              Quiet; do not write anything to standard output.  Exit immediately with zero status if any match is found, even if an error
              was detected.  Also see the -s or --no-messages option.

       -s, --no-messages
              Suppress error messages about nonexistent or unreadable files.

       -b, --byte-offset
              Print  the  0-based  byte  offset  within the input file before each line of output.  If -o (--only-matching) is specified,
              print the offset of the matching part itself.

       -H, --with-filename
              Print the file name for each match.  This is the default when there is more than one file to search.

       -h, --no-filename
              Suppress the prefixing of file names on output.  This is the default when there is only one file (or only  standard  input)
              to search.

       --label=LABEL
              Display  input  actually  coming  from  standard  input  as  input  coming from file LABEL.  This is especially useful when
              implementing tools like zgrep, e.g., gzip -cd foo.gz | grep --label=foo -H something.  See also the -H option.

       -n, --line-number
              Prefix each line of output with the 1-based line number within its input file.

       -T, --initial-tab
              Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs  looks  normal.
              This  is  useful  with  options  that  prefix  their  output to the actual content: -H,-n, and -b.  In order to improve the
              probability that lines from a single file will all start at the same column, this also causes  the  line  number  and  byte
              offset (if present) to be printed in a minimum size field width.

       -u, --unix-byte-offsets
              Report Unix-style byte offsets.  This switch causes grep to report byte offsets as if the file were a Unix-style text file,
              i.e., with CR characters stripped off.  This will produce results identical to running grep on a Unix machine.  This option
              has no effect unless -b option is also used; it has no effect on platforms other than MS-DOS and MS-Windows.

       -Z, --null
              Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.  For example, grep
              -lZ outputs a zero byte after each file name instead of the usual newline.  This option makes the output unambiguous,  even
              in the presence of file names containing unusual characters like newlines.  This option can be used with commands like find
              -print0, perl -0, sort -z, and xargs -0 to process arbitrary file names, even those that contain newline characters.

       -A NUM, --after-context=NUM
              Print NUM lines of trailing context after matching lines.   Places  a  line  containing  a  group  separator  (--)  between
              contiguous groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

       -B NUM, --before-context=NUM
              Print  NUM  lines  of  leading  context  before  matching  lines.   Places a line containing a group separator (--) between
              contiguous groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

       -C NUM, -NUM, --context=NUM
              Print NUM lines of output context.  Places a line containing a group separator (--) between contiguous groups  of  matches.
              With the -o or --only-matching option, this has no effect and a warning is given.

       --line-buffered
              Use line buffering on output.  This can cause a performance penalty.

       -z, --null-data
              Treat  input  and  output data as sequences of lines, each terminated by a zero byte (the ASCII NUL character) instead of a
              newline.  Like the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.
```

</div></details>

`-z`で、入力と出力のデータをnull文字（¥0）区切りとすることができる。空白や制御文字を含むファイル名を扱う場合に使用する。

## まとめ

予想していた通り、ls、find、grepコマンドはかなり奥の深いコマンド達でしたね。
この記事を書くためにこれらのコマンドとしばらく向き合ったおかげで、かなり仲良くなれた気がします。
それぞれのコマンドだけでも十分強力でしたが、これらのコマンドを-execやパイプを使って組み合わせて使えば、もうファイル検索は自由自在ですね。

みなさんもどんどん活用して、ls、find、grepコマンドと生涯の友となりましょう！

## 参考
http://man7.org/linux/man-pages/index.html
https://linuxjm.osdn.jp/