8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

findコマンドで一部のディレクトリを除外した際に得た理解

Posted at

findコマンドで一部のディレクトリを除外するためにpruneというオプションを利用した。このときに得た理解をメモしておく。

「find ディレクトリ 除外」で検索するとfindコマンドとpruneオプションを利用したテクニックが手に入る

Googleで「find ディレクトリ 除外」などで検索すると__prune__オプションを利用したコマンド例が挙がってくる。

#「test-」から始まるディレクトリを除外し、一覧する
find . -type d -name "test-*" -prune -o -print

実行例を検証

実行は前提としてこのようなディレクトリ構成を想定し実行している

そして、findコマンドを実行してみる。

$ find . -type d -name "test-*" -prune -o -print
.
./file2.txt
./file1.txt
./hoge-dir1
./hoge-dir1/file2.txt
./hoge-dir1/file1.txt
./hoge-dir2
./hoge-dir2/file2.txt
./hoge-dir2/file1.txt
./hoge-dir3
./hoge-dir3/file2.txt
./hoge-dir3/file1.txt

確かに、_test-*_から始まるディレクトリが除外された一覧が取得出来る。

新しい疑問 「-o -print」って何だ

このとき、「findコマンドでpruneオプションを利用すれば、特定のディレクトリが除外できるんだ!」と理解したのだが、新しい疑問が生まれ混乱した。「-o -printオプション」はなんで必要なんだ。

prune オプションは除外するオプションではない

結果的にはpruneオプションを利用することで要求を解決出来るのだが、この時に「pruneオプションは、除外するためのオプション」という理解をするのは混乱を招く。

前提

以下のような構成のディレクトリを前提に話を進めている。

$ tree
.
├── file1.txt
├── file2.txt
├── hoge-dir1
│   ├── file1.txt
│   └── file2.txt
├── hoge-dir2
│   ├── file1.txt
│   └── file2.txt
├── hoge-dir3
│   ├── file1.txt
│   └── file2.txt
├── test-dir1
│   ├── file1.txt
│   ├── file2.txt
│   ├── test-dir1
│   │   ├── file1.txt
│   │   ├── file2.txt
│   │   ├── test-file1.txt
│   │   └── test-file2.txt
│   ├── test-file1.txt
│   └── test-file2.txt
├── test-dir2
│   ├── file1.txt
│   ├── file2.txt
│   └── test-dir
│       ├── file1.txt
│       ├── file2.txt
│       ├── test-file1.txt
│       └── test-file2.txt
└── test-dir3
    ├── file1.txt
    ├── file2.txt
    └── test-dir3
        ├── file1.txt
        ├── file2.txt
        ├── test-file1.txt
        └── test-file2.txt

pruneオプションは真を返す

findコマンドでpruneオプションを付加した場合、条件に該当するモノを見つけ結果として真を返す。

それがディレクトリだった場合は、そのディレクトリのより下の階層の検索は行わない。この動作を枝刈り、枝切り、枝探し、切り取りと表現していて、pruneの動詞的な意味なんだと理解出来る。

実行例

実際にコマンドを実行してみると、以下のような結果が得られる。

$ find . -type d -name "test-*" -prune
./test-dir1
./test-dir2
./test-dir3

findは結果が真だった場合、その対象を標準出力にパス付きで表示するようになっているらしい。そのため、「test-」から始まる3つのディレクトリは結果が真となり出力される。さらにこれらのディレクトリの中には「test-」から始まるディレクトリが含まれているが、pruneオプションによって真となったディレクトリより下のディレクトリは検索しないという動作になる為それらは出力(検査)されない。

-o はORの意味

findコマンドを利用する際に複数の条件を論理和として評価したい場合に使う。

はい、でしょうね。知ってました。で、何故それが必要なのか。そして右辺で-printする理由。その結果特定のディレクトリを除外した結果が得られるのか。

-print は標準出力への結果出力

__findでは結果が真となったファイルやディレクトリをパス付きで標準出力に出力する__と説明は実は言葉足らず。この動作は−printなどのオプションがfindコマンドに指定されていない場合の話。
今回のコマンド構成の場合、-oオプションの右辺に-printが指定されているため、左辺の結果に対する出力が行われないことになる。右辺の真に対してのみ出力が行われる。

-pruneオプションによって結果が除外されるのはなぜ

今回のコマンドの構成を改めて確認して見る。

#「test-」から始まるディレクトリを除外し、一覧する
find . -type d -name "test-*" -prune -o                    -print
#      ~~~~~~左辺の条件~~~~~~            ~~~~~~右辺の条件~~~~~~ 

左辺の条件

 __-type d -name "test-*"__この条件を満たしたファイルは真となる。

右辺の条件

何もない、要は無条件。

短絡評価ってことか

ORで繋がれた二つの条件がある場合、一つ目の条件が真である場合二つ目の評価をする必要がない。だから二つ目を評価しない

  1. 要するに、左辺の条件を満たファイルはpruneオプションによって真となる。その為、右辺の処理がされないことになる。printオプションは右辺にあるため、右辺を評価しない場合は出力されないことになる。
  2. 左辺の条件を満たさなかった場合はどうなるかというと、右辺の条件が評価される。
  3. しかし、右辺には条件がない->要するに__無条件__。無条件で__-print__されることになる。
8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?