Unixの検索


1. `grep` ファイルに保存されている内容を調べる
1. `locate` ファイル名だけからファイルを見つけ出す（あらかじめファイル名を管理するデータベースを作成しておくので高速）
1. `find` `locate`コマンド以上に洗練された処理が可能
1. Spotlight Mac OS Xのみ

## `grep`コマンド

### 代表的な`grep`オプション

|オプション|説明|
|:--|:--|
|-A 数|一致した行の後、「数」行分を書き出す|
|-B 数|一致した行の前、「数」行分書き出す|
|-C 数|一致した行の前後、「数」行分を書き出す|
|-v|パターンと一致しない行を書き出す|
|-n|パターンと一致した行と、行番号を書き出す|
|-l|パターンと一致した行を含むファイル名だけを書き出す|
|-c|パターンと一致した行数だけ書き出す|
|-i|大文字と小文字の違いを無視して検索する|

- 「Jane」という単語を含んでいないファイルをすべて探しだす

``` Bash
grep -lv Jane *
```

- 一致部分の強調表示
`--color=always`

``` Bash
grep --color=always text sample
```
こんな感じになる
![1__root_dti-vps-srv742__var_lib_redmine__bash_.png](https://qiita-image-store.s3.amazonaws.com/0/4476/7ccf39f0-7e92-bfa0-05d7-d3125ae43d8a.png "1__root_dti-vps-srv742__var_lib_redmine__bash_.png")

bashシェルを使っているなら、ホームディレクトリにある`.profile`ファイル内に次の行を追加しておくと良い

```
GREP_OPTIONS="--color always";export GREP_OPTIONS
```

### 正規表現
####正規表現であらかじめ決められた表記方法
|表記|説明|
|:--|:--|
|[:alnum:]|大文字と小文字、ならびに数字（0から9）|
|[:alpha:]|大文字と小文字|
|[:digit:]|数字（0から9）|
|[:lower:]|小文字|
|[:print:]|表示可能な文字|
|[:punct:]|句読点|
|[:space:]|半角空白記号と同様に扱える文字の集合（スペース記号、タブ記号、行末記号など|
|[:upper:]|大文字|
|[:xdigit:]|16進の数値（0から9と、aからf、または、AからF）|


- キャレット記号(^)
	- 角括弧記号で挟まれていない場所で使用：行頭に一致
	- 角括弧記号挟まれた場所で使用：否定
- .(ピリオド): 一文字
- \\: エスケープ記号

####繰り返しを表す演算子
- $: 行末
- ?: 直前に書いたパターンが、あってもなくてもよい、かつ、最大でも1回だけ現れる
- *: 直前に書いたパターンがなくてもよいし、逆に何回繰り返し現れてもよい
- +: 直前に書いたパターンが、最低1つは存在しなければならず、かつ、何回繰り返し現れても良い
- {数}: 直前に書いたパターンが「数」の回数、現れなければならない
- {数1,数2}: 直前に書いたパターンが、「数1」から「数2」の間の回数、必要

(|): 復数の正規表現を同時に併記して、どちらかの正規表現だけに当てはまるものと一致させることができる 
例）(cat|dog)house という正規表現は「cathouse」にも、「doghouse」にもどちらでも一致させることができる

## `find`コマンド
`find いくつかのオプション 探索開始パス名 式`

- 作業ディレクトリ下に存在するHTMLファイルをすべて探しだす

```Bash
find . -name "*.html" -print
```

- 行数を計算するwcコマンドに渡し、一致したものの個数だけをウィンドウに書き出す

```Bash
find $HOME -name "*.html" -print | wc -l
```

### ファイル容量による一致
`-size` オプション  
容量を指定する基本単位: 512バイト
すなわち、`-size 10`と指定したら、容量が10×512バイトのファイルと一致することになる

指定したバイト数そのものと一致させるには、適用値に`c`を付ける 
たとえば、`-size 10c`と指定すれば、容量が10バイトのファイルと一致する

- `+`: 〜バイトを超える
5キロバイトを超えるファイルだけを探すなら、`-size +10` or `-size +5120c`

- `-`: 〜バイトに満たない
100バイトに満たないファイルを見つけ出すなら、`-size -100c`

### 覚えておくとよい便利なfindコマンドの使い方
|基本要素|説明|
|:--|:--|
|-cmin 数|ここ「数」分以内に変更されたファイルに一致|
|-ctime 数|ここ「数」時間以内に変更されたファイルに一致|
|-group グループ名|「グループ名」というグループに所属しているファイルに一致|
|-iname パターン|大文字と小文字を無視して検査すること以外、`-name`と同じ|
|-iregex 正規表現|大文字と小文字を無視して検査すること以外、`-regex`と同じ|
|-ls|一致したファイルに対する結果として`ls -l`を書き出す|
|-name パターン|指定した「パターン」に合う名前を持つファイルに一致|
|-nouser|`/etc/passwd`ファイル内に登録されていない未知の利用者が所有しているファイルに一致|
|-perm アクセス権|指定した「アクセス権」を持っているファイルと一致。この基本要素は複雑なので後述|
|-print|一致した完全パス名を書き出す|
|-print0|結果の書き出しで行末コードの代わりにASCII NULLコードを使うこと以外、`-print`と同じ。OS Xで`find`コマンドを使う上できわめて重宝する|
|-regex 正規表現|単純なファイルパターンを使う代わりに、完全な「正規表現」を使用すること以外、`-name`と同じ|
|-size 数|指定した「数」のファイルと容量が一致。標準で512バイト単位で計算。「数」の後ろに`c`を付けるとバイト単位で計算。「数」の前に`+`を付けると「数」を超える容量のファイルと一致。「数」の前に`-`を付けると「数」に満たない容量のファイルと一致|
|-type タイプ|「タイプ」で指定した種類のファイルと一致。「d」を指定するとディレクトリ、「f」を指定すると普通のファイルと一致|
|-user 名前|オーナーが「名前」になっているファイルと一致。「名前」にはユーザ名の他、ユーザIDも使える|
 
- シンボリックリンクではなく、本当のファイルだけ一致するように指定する

```Bash
~ (431)$ find /bin/ -size +60 -type f -ls
67652587     1208 -r-xr-xr-x    1 root             wheel             1228240 10 25 05:46 /bin//bash
67974966      360 -rwxr-xr-x    2 root             wheel              357984 10 25 05:56 /bin//csh
67653777       56 -rwxr-xr-x    1 root             wheel               49984 10 25 05:46 /bin//ed
67932077     1288 -r-xr-xr-x    1 root             wheel             1315248 10 25 05:55 /bin//ksh
67653194       72 -r-xr-xr-x    1 root             wheel               73600 10 25 05:46 /bin//launchctl
67653023       32 -rwxr-xr-x    1 root             wheel               34736 10 25 05:46 /bin//ls
67653026      104 -rwxr-xr-x    1 root             wheel              107024 10 25 05:46 /bin//pax
67652419       40 -rwsr-xr-x    1 root             wheel               46784 10 25 05:46 /bin//ps
67652588     1216 -r-xr-xr-x    1 root             wheel             1228304 10 25 05:46 /bin//sh
67652420       24 -rwxr-xr-x    1 root             wheel               32272 10 25 05:46 /bin//stty
67653754       16 -rwxr-xr-x    1 root             wheel               34304 10 25 05:46 /bin//sync
67974966      360 -rwxr-xr-x    2 root             wheel              357984 10 25 05:56 /bin//tcsh
67975594      584 -rwxr-xr-x    1 root             wheel              530320 10 25 05:56 /bin//zsh
~ (432)$
```
この出力結果は普通に`ls -l`を実行した場合と若干違うが、ファイルのパーミッション（アクセス権）、オーナー、ファイルの所属するグループ、ファイル容量、最終修正日などが示されている。

### パーミッションを指定して`find`を使用
`chmod`コマンドと同じパーミッション指定方法を使うのを念頭に置くこと。 
パーミッションを指定する文字は次の順序で並んでいる
`` 対象 操作 許可``

- `対象`
	- `a`: すべてを示す
	- `u`: ファイルのオーナーを示す
	- `g`: ファイルが所属するグループを示す
	- `o`: ファイルのオーナーでもオーナーが所属するグループの一員でもない者たちを示す
- `操作`: `find`の指定に使えるのは`=`だけ
- `許可`
	- `r`: 読み出し許可
	- `w`: 書き込み許可
	- `x`: 実行許可
	- `s`: 実行時にユーザIDを設定、または、実行時にグループIDを設定する特別な許可

 
`/usr/bin`ディレクトリ下で、小文字の「z」から始まるファイル名で、ファイルのオーナーに書き込み許可が与えられているファイルを見つけ出す

```Bash
~ (436)$ find /usr/bin/ -name "z*" -type f -perm +u=w -print
/usr/bin//zcat
/usr/bin//zcmp
/usr/bin//zdiff
/usr/bin//zegrep
/usr/bin//zfgrep
/usr/bin//zforce
/usr/bin//zgrep
/usr/bin//zip
/usr/bin//zipcloak
/usr/bin//zipdetails
/usr/bin//zipdetails5.16
/usr/bin//zipgrep
/usr/bin//zipinfo
/usr/bin//zipnote
/usr/bin//zipsplit
/usr/bin//zless
/usr/bin//zmore
/usr/bin//znew
/usr/bin//zprint
~ (437)$ ls -l /usr/bin/zcat
-rwxr-xr-x  4 root  wheel  43200 10 25 05:56 /usr/bin/zcat*
```

`find`コマンドを実行した利用者が書き込み許可を持っているファイルを探し出すには、`-user`も指定しておく必要

```Bash
~ (438)$ find /usr/bin/ -name "z*" -type f -user $USER -perm +u=w -print
~ (439)$
```

### 最近変更されたファイルを`find`で検索
- 60分以内に変更されたファイル

```Bash
find . -cmin -60 -print -type -f
```

- 10分以内に修正されたルートユーザがオーナーの全ファイル

```Bash
~ (441): sudo find / -cmin -10 -type f -user root -print
Password:
/.Spotlight-V100/Store-V2/74967323-F6E6-4561-BF66-90BA969A2163/.store.db
/.Spotlight-V100/Store-V2/74967323-F6E6-4561-BF66-90BA969A2163/1.indexGroups
/.Spotlight-V100/Store-V2/74967323-F6E6-4561-BF66-90BA969A2163/live.2.indexIds
...
```

### `find`の頼れる相棒: `xargs`コマンド

```Bash
find | xargs grep パターン
```

上記がone,two,threeという3つのファイル名を含んでいるとすると、`grep`コマンドが次のような呼び出しに変更されたと考えられる

```Bash
grep パターン one two three

```

```Bash
find /var/log/ -not -name "*gz" -type f -size +0 -print | sudo xargs grep -i warningoki
```

## 参考

[入門 Unix for OS X](http://www.oreilly.co.jp/books/9784873116440/) 5.1〜5.3