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'
になる 。
つまり、このように解釈する。
- not expr1 が評価され合致したら、not で否定され、not expr2 は評価されない。
- 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 、これらをぱぱっと使いこなすのは、熟練の技みたいになってますねぇ。。
関連資料
参考資料
man find