The Silver Searcher のススメ

# What is The Silver Searcher
[The Silver Searcher](https://github.com/ggreer/the_silver_searcher/blob/master/doc/ag.1.md)

ファイルに対して再帰的に文字列検索を行なうコマンドです。要はスゴイ grep です。Silver だから ag というコマンド名という。

# Why The Silver Searcher
- とても速い。
  - Pthreads を使用し並列処理を行なう。

- .git や .svn を検索除外してくれる。
  - .gitignore の内容も除外してくれる。
    - ag のみで除外したい場合は .agignore というファイルも利用可能。

- 検索対象ファイルのファイルタイプをオプション指定できる。
  - --ruby と指定すると (.rb  .rhtml  .rjs  .rxml  .erb  .rake  .spec) が対象になる。

# インストール
## OS X
Homebrew で

```
$ brew install the_silver_searcher
```

## Debian系

```
$ sudo apt install silversearcher-ag
```

## RHEL系

```
$ sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
$ sudo yum install the_silver_searcher
```

## Fedora 22以降

```
$ sudo dnf install the_silver_searcher
```

# 使い方
## カレントディレクトリ以下を検索

```
$ ag pthread
```

## 特定ディレクトリ以下を検索

```
$ ag pthread /usr/src
```

## 圧縮ファイルも検索

```
$ ag -z pthread
```

対応しているファイルフォーマットは以下の表の通り。xz は対応済みだが、bzip2 は非対応な点に注意。

フォーマット                                                                                                                                    | 対応状況
:---------------------------------------------------------------------------------------------------------------------------------------: | :--:
[gzip](https://ja.wikipedia.org/wiki/Gzip)                                                                                                | o
[bzip2](https://ja.wikipedia.org/wiki/Bzip2)                                                                                              | x
[xz](https://ja.wikipedia.org/wiki/Xz_%28%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%29)   | o
[UNIX Compress](https://ja.wikipedia.org/wiki/UNIX_Compress)                                                                              | x
[ZIP](https://ja.wikipedia.org/wiki/ZIP_%28%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%29) | x

ちなみに各種ツールを process fork して呼び出してるわけではなく、[ag 自体で decompress](https://github.com/ggreer/the_silver_searcher/blob/master/src/decompress.c) しています。速度へのこだわりがすごい。

## ファイル/ディレクトリ名のパターンを指定して検索

```
$ ag -G '\.(c|h)' pthread
```

パターンは正規表現で指定するため、shell の glob っぽく *.c と記載すると動かないので注意。

## ファイルタイプを指定して検索

```
$ ag --cc pthread
```

一般的によく使われるであろう言語については下記の通り対応済み。

FILE TYPE | suffix
:-------- | :--------------------------------------
--cc      | .c .h .xs
--cpp     | .cpp .cc .C .cxx .m .hpp .hh .h .H .hxx
--html    | .htm .html .shtml .xhtml
--java    | .java .properties
--js      | .js .jsx
--perl    | .pl .pm .pm6 .pod .t
--php     | .php .phpt .php3 .php4 .php5 .phtml
--python  | .py
--ruby    | .rb .rhtml .rjs .rxml .erb .rake .spec
--shell   | .sh .bash .csh .tcsh .ksh .zsh
--xml     | .xml .dtd .xsl .xslt .ent
--yaml    | .yaml .yml

他の言語についても対応しているかどうかは下記コマンドで確認可能です。

```
$ ag --list-file-types
```

## 隠しファイルも検索

```
$ ag --hidden pthread
```

隠しファイルとは '.' から始まるファイルやディレクトリです。

## 全ファイルを検索

```
$ ag -u pthread
```

.agignore や .gitignore の内容も無視し、上記の隠しファイルも含めて全てのファイルを検索対象とします。

## マッチしたファイル名だけ表示

```
$ ag -l pthread
```

ちなみに `ag -l` で検索対象ファイルの全表示になります。

## マッチしなかったファイル名だけ表示

```
$ ag -L pthread
```

上記の逆ですね。

## ファイル名(相対パス含む)に対して検索

```
$ ag -g pthread
```

上記の -l はファイル内容にマッチしたファイル名のみ表示。こちらの -g はファイル名にマッチしたら表示。ややこしい。

## 再帰処理するディレクトリ階層の深さを指定

```
$ ag --depth 1 pthread
```

- 0 を指定すると指定したディレクトリのみ。
- 1 を指定すると 1階層までディレクトリ再帰処理する。
- -1 を指定すると無限に再帰処理する。
  - デフォルトは 25。

## セパレーターを NULL にして表示

```
$ ag -0 pthread
```

詳細は下記応用例で。

# 応用例
## ファイル名が FILE_PATTERN にマッチして、かつ、PATTERN が含まれているファイル名を表示したい

```
$ ag -l -G FILE_PATTERN PATTERN
```

`-l -g` だとダメなので注意。

## PATTERN が含まれているファイルに xargs で COMMAND 処理を行なう

```
$ ag -l -0 PATTERN | xargs -0 COMMAND
```

`ag -0` は find(1) でいうところの `-print0` と同等で、ファイル名に空白が含まれていると xargs(1) 側でうまく処理ができないのが理由です。

# Atom から使いたいよ
[atom-fuzzy-grep](https://atom.io/packages/atom-fuzzy-grep) を使うと便利。

![atom-fuzzy-grep](https://i.github-camo.com/7819d532ad92f98c1391e464c70d0248f7111b5b/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f67656b73696c6c612f61746f6d2d66757a7a792d677265702f6d61737465722f64656d6f2e676966) ↑ こんな感じでプロジェクトに含まれるファイル郡から fuzzy 検索できるようになります。 あまりに大量にファイルがあると結果出てくるまでに数秒かかったり結果リストがリアルタイムに更新されたりするけど、慣れれば気にならない予感。

自分の環境(OSX El Capitan + Homebrew + Homebrew Cask)だと ag がみつからないとエラーになってしまうので、設定画面で `/usr/local/bin/ag -i --nocolor --nogroup --column` を設定して解決。 同様の Issue が [Failed to spawn command `ag` on second window](https://github.com/geksilla/atom-fuzzy-grep/issues/16) として報告されてますなー。

ちなみに Atom 標準の [Find and Replace package](https://github.com/atom/find-and-replace) の Find in project のように新しいタブを開いて検索結果をリストアップ、という Package はまだない模様。

# 似たツールはないのかな
## ack
[ack](http://beyondgrep.com/)

高速grepツールの草分け?

perl で書かれているので ag と比較すると若干処理に時間がかかる。というより ag はスピードを追求した ack という出自っぽい。

## sift
[sift](https://sift-tool.org/)

ag よりも速いし高機能のようだけど、メモリー使用量が結構すごいらしい(未検証)。

## highway
[highway](https://github.com/tkengo/highway)

ag よりも速い(手元の環境で確かに速かった)上に、EUC-JP や Shift-JIS にも対応していてステキ。

`--column` オプションがないので、上記の atom-fuzz-grep はうまく動かない模様…。unite.vim だと動くようなのに…。

[highway という高速検索ツールを作りました](http://tkengo.github.io/blog/2015/10/19/release-highway/)

## The Platinum Searcher
[The Platinum Searcher](https://github.com/monochromegane/the_platinum_searcher)

ag 相当の速度で Go で書かれていて、EUC-JP や Shift-JIS にも対応。

[Go言語でag(The Silver Searcher)ライクな高速検索ツールをつくった。EUC-JP/Shift-JISも検索できマス。](http://blog.monochromegane.com/blog/2014/01/16/the-platinum-searcher/)

# まとめ
高速grepツールの進化がすごいので、これからも便利になる予感。

Atom の Find in project のような使い勝手で使えるようになるといいなー。そのうち自分で作るかもだけど、そもそも JavaScript 書けないしなー、とか。