light log

学んだこととか

findコマンドをちょっと調べた

あんまり使いこなしてなかったのでちょっと調べた。

環境はMacbash

以下の形式で使う。

find 起点のディレクトリ [検索条件] [アクション]

検索条件とアクションは省略可能。

検索条件を省略すると、起点のディレクトリ配下のファイルとディレクトリが全てヒットする。

アクションを省略すると-printを指定したときと同じ結果になり、ヒットしたパスが出力される。

準備

実験用のディレクトリ/ファイルを作成する。

$ mkdir AAA BBB CCC DDD
$ for i in `ls -1`; do touch $i/{aaa,bbb,ccc,ddd}.txt; done

ということで今回は以下の構成で遊んでみる。

$ tree
.
├── AAA
│   ├── aaa.txt
│   ├── bbb.txt
│   ├── ccc.txt
│   └── ddd.txt
├── BBB
│   ├── aaa.txt
│   ├── bbb.txt
│   ├── ccc.txt
│   └── ddd.txt
├── CCC
│   ├── aaa.txt
│   ├── bbb.txt
│   ├── ccc.txt
│   └── ddd.txt
└── DDD
    ├── aaa.txt
    ├── bbb.txt
    ├── ccc.txt
    └── ddd.txt

4 directories, 16 files

検索条件

起点のディレクトリだけ指定すると、配下のファイルとディレクトリが再帰的に全部出力される。

$ find .
.
./AAA
./AAA/aaa.txt
./AAA/bbb.txt
./AAA/ccc.txt
./AAA/ddd.txt
./BBB
./BBB/aaa.txt
./BBB/bbb.txt
./BBB/ccc.txt
./BBB/ddd.txt
./CCC
./CCC/aaa.txt
./CCC/bbb.txt
./CCC/ccc.txt
./CCC/ddd.txt
./DDD
./DDD/aaa.txt
./DDD/bbb.txt
./DDD/ccc.txt
./DDD/ddd.txt

-type fオプションを指定するとファイルのみ、-type dでディレクトリのみ出力。

$ find . -type f
./AAA/aaa.txt
./AAA/bbb.txt
./AAA/ccc.txt
./AAA/ddd.txt
./BBB/aaa.txt
./BBB/bbb.txt
./BBB/ccc.txt
./BBB/ddd.txt
./CCC/aaa.txt
./CCC/bbb.txt
./CCC/ccc.txt
./CCC/ddd.txt
./DDD/aaa.txt
./DDD/bbb.txt
./DDD/ccc.txt
./DDD/ddd.txt
$ find . -type d
.
./AAA
./BBB
./CCC
./DDD

-nameオプションで検索するファイル名のパターンを指定する。

$ find . -name a*
./AAA/aaa.txt
./BBB/aaa.txt
./CCC/aaa.txt
./DDD/aaa.txt

-orでOR条件。

-andでAND条件だけど、普通に条件を並べればANDになるので明示は不要。

$ find . -name a* -or -name c*
./AAA/aaa.txt
./AAA/ccc.txt
./BBB/aaa.txt
./BBB/ccc.txt
./CCC/aaa.txt
./CCC/ccc.txt
./DDD/aaa.txt
./DDD/ccc.txt

!で条件の否定。

$ find . ! -name a* -type f
./AAA/bbb.txt
./AAA/ccc.txt
./AAA/ddd.txt
./BBB/bbb.txt
./BBB/ccc.txt
./BBB/ddd.txt
./CCC/bbb.txt
./CCC/ccc.txt
./CCC/ddd.txt
./DDD/bbb.txt
./DDD/ccc.txt
./DDD/ddd.txt

-regex正規表現も使える。

$ find . -regex '.*A.*b.*'
./AAA/bbb.txt

アクション

見つかった各ファイルに対して行うアクションも指定できる。

-printを指定したときの結果は、アクションを何も指定しなかったときと同じ。言い換えると、何も指定しなかったときは-printを指定したとみなされる。

$ find . -print
.
./AAA
./AAA/aaa.txt
./AAA/bbb.txt
./AAA/ccc.txt
./AAA/ddd.txt
./BBB
./BBB/aaa.txt
./BBB/bbb.txt
./BBB/ccc.txt
./BBB/ddd.txt
./CCC
./CCC/aaa.txt
./CCC/bbb.txt
./CCC/ccc.txt
./CCC/ddd.txt
./DDD
./DDD/aaa.txt
./DDD/bbb.txt
./DDD/ccc.txt
./DDD/ddd.txt

-lsは、検索結果を詳細に(ls -lと同じような形式で)出力する。(結果は省略)

$ find . -ls 

-execで実行するコマンドを指定できる。以下で配下のファイルを全て削除する。

{}はヒットしたファイルを表す。;の前の\は、シェルに解釈されずfindに;を引き渡すためのエスケープ。

$ find . -type f -exec rm {} \;

-ok-execと同じだが、コマンドの実行前に確認メッセージが出る。

$ find . -ok rm -r {} \;

綺麗になりました。

$ ls -a
.   ..

まとめ

まだまだオプションあるけど、とりあえずはこれくらい知っておけばよさそう。

参考