それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

find コマンドで指定条件を除外(exclude)して、特定の拡張子を対象から消すには

find コマンドで指定条件のファイルを<除外>したい時

ずっとgrep 使ってたんですけど、find だけで出来ないのかなと気になって調べました。

-not -name pattern のように出来る

除外するときは、-not を最初につけてから上限を書けばいいことがわかった。

次の例は、拡張子 jpg を除外する場合

 find -type f -not -name '*jpg'

条件として記述するので name 以外にもファイル名やパーミッションなど find コマンドのオプションと -notを組み合わせて、◯◯以外の条件にマッチしたものを除く、といったファイルの検索できることがわかる。

複数条件書いたらどうなるのか

-not があれば、気になるのが複数条件

 find -type f -not -name '*jpg' -not -name '*.png'

このように、複数続けて書いたら、( not A and not B ) になる。つまり、jpg ファイルと png ファイルを除外できる。ふむ。-not による条件の重ねがけは絞り込みじゃなく、not の 和集合になるようです

結論:除外したい条件を書くときは

-not つけて並べておけば大丈夫!

コレが一番わかり易いですよね。

もっと細い not expr not expr の話。

カンタンな結論だと、not つけて並べておけば大丈夫ってことなんですが否定入ると、論理の世界なので、and/or をちゃんと意識しておいたほうがイイ感じた。 なので、and/or をちゃんと把握するためにももう少し調べてみる。

気になったので man を調べました。

条件に関する man の記述は以下のとおり

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

       expr1 expr2
              Two expressions in a row are taken to be joined with an implied "and"; 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  travers‐
              ing the filesystem hierarchy only once.  The -fprintf action can be used to list the various matched items into several different output files.

条件を並べて書くのは 暗黙の and

expr1 expr2 は expr1 -and expr2 と同じ

このように、条件を並べて書くのは、暗黙のand として扱われる。したがってexpr1 が false のときは、expr2 は評価されない。

つまり、expr1 が評価され合致したら、expr2 が評価される。 更に言うと、expr1 で絞り込んだ後、expr2 で更に絞り込まれる。

-not expr は普通の expr の扱いになる

-not expr は not の付いた1つのexpr と解釈される

-not -name '*.txt' -not -name '*.php'

このように書いた場合、-not -name '*.txt' and -not -name '*.php' になる 。

つまり、このように解釈する。

  1. not expr1 が評価され合致したら、not で否定され、not expr2 は評価されない。
  2. not expr1 が評価され不一致なら、not で否定され、not expr2 が評価される。

表にするとこんな感じ

not expr1 expr1 not expr2
false マッチする evalされない
true マッチしない eval される

具体例 find -not -name '*.jpg' -not -name '*.png' の場合

具体例を書くとこんな感じ。

ファイル名 -name '*.jpg' -not -name '*.jpg' -name '*.png' -not -name '*.png' 結果
hoge.jpg true false skip skip false / 出力されない
hoge.png false true true false false / 出力されない
hoge.txt false true false true true / 結果に出る

このようになる。

find 奥が深い

find って単純に、条件を列挙してたけど、実は and 結合になっていて not と or も使えるんですね。奥が深い、でもここまで使い込むかなぁ。複数回コマンド実行して結果を結合しちゃうよね・・・

find を使っていくうえで憶えることは、たくさんですね。

条件に関することも、exec に関すること、 POSIX互換部分、GNU追加機能、日付、パーミッション....etc findには知っておくと便利なことがたくさん。 たかが find されど find 、これらをぱぱっと使いこなすのは、熟練の技みたいになってますねぇ。。

関連資料

find コマンド関連の他の記事はこちら

参考資料

man find