find の -permを使う tips
findの中でも有用なのだが使いにくいものに -perm オプションがある。fileの permissionを条件にするものだ。
という書き出しにしてみたが、そんなに permオプション使うかな、正直なところ。このまえ、自分が読めないファイルを見つけるために
find . ! -perm +044
とかやったけど*1。それ以前に使ったのは1ヶ月前だしな。でも弾さんのblogでネタ振りしてくれたんで勉強がてらくらいついておこう。
前提
こんなスクリプトで "test" ディレクトリ以下に 512個ファイルを作っておく。
#!/usr/bin/perl for ($i = 0; $i < 512; $i++) { $_ = sprintf("%03o", $i); s/0/---/g; s/1/--x/g; s/2/-w-/g; s/3/-wx/g; s/4/r--/g; s/5/r-x/g; s/6/rw-/g; s/7/rwx/g; open TOUCH, ">$_"; close TOUCH; chmod $i, $_; }
作ったファイルは以下のようになるわけだ。ファイル名と permissionが一致しているのに注意:
[11:19]jargon:find-test<212> ls test -l |head total 0 ---------- 1 hujikojp hujikojp 0 2007-03-31 10:57 --------- -------r-- 1 hujikojp hujikojp 0 2007-03-31 10:57 ------r-- ----r----- 1 hujikojp hujikojp 0 2007-03-31 10:57 ---r----- -r-------- 1 hujikojp hujikojp 0 2007-03-31 10:57 r-------- ----r--r-- 1 hujikojp hujikojp 0 2007-03-31 10:57 ---r--r-- -r-----r-- 1 hujikojp hujikojp 0 2007-03-31 10:57 r-----r-- -r--r----- 1 hujikojp hujikojp 0 2007-03-31 10:57 r--r----- -r--r--r-- 1 hujikojp hujikojp 0 2007-03-31 10:57 r--r--r-- -r--r--rw- 1 hujikojp hujikojp 0 2007-03-31 10:57 r--r--rw-
8進数表記の場合
permオプションの場合、8進数表記のほうがわかりやすい気がする。これがわからない人は「404 Blog Not Found:unix - permissionあれこれ」でも見てくれ。
まず単純に普通に数値を指定すると exactly matchだ。
[12:02]jargon:find-test<215> find test -perm 444 test/r--r--r--
しかしどうでもいい bitも多いので +/- という記法もある。まず "-" は 「andみたいなもの」と覚えておくといい。
[12:03]jargon:find-test<216> find test -perm -444 |head test test/r--r--r-- test/r--r--r-x test/r--r--rw- test/r--r--rwx test/r--r-xr-- test/r--r-xr-x test/r--r-xrw- test/r--r-xrwx test/r--rw-r--
出てきたファイルすべて r..r..r..
と、引数に対応した bitが立っていることがわかるだろう *2。
ちょっと厳密に言うと、引数に指定したのを smask, 対象となるファイルの permissionを dmaskとすると、以下の条件のときに(かつそのときに限り) 真となる:
(smaks & dmask) == smask
演習問題 0:
以下の結果は? (test自体が入ることを忘れないよう)
find test -perm -444 | wc -l
"+" は「orみたいなもの」だ。
[12:04]jargon:find-test<217> find test -perm +444 | head test test/------r-- test/------r-x test/------rw- test/------rwx test/-----xr-- test/-----xr-x test/-----xrw- test/-----xrwx test/----w-r-- [12:06]jargon:find-test<218> find test -perm +444 | tail test/rwxrw-rw- test/rwxrw-rwx test/rwxrwx--- test/rwxrwx--x test/rwxrwx-w- test/rwxrwx-wx test/rwxrwxr-- test/rwxrwxr-x test/rwxrwxrw- test/rwxrwxrwx
ちとわかりにくいが、三つの rのうち (引数のうち、bitのたっているものに相当)、 どれかひとつでも立っていれば出力されている。先ほどと同じ風に条件を書くと以下のとおり:
(smask & dmask) != 0
演習問題 1:
以下の結果は? (test自体が入ることを忘れないよう)
find test -perm +444 | wc -l
以上、bitが立っていることしか表現できないので、bitが寝ていることを条件にするには "!" と組み合わせる。
[12:08]jargon:find-test<220> find test \! -perm +44 | tail test/rwx--x-w- test/rwx--x-wx test/rwx-w---- test/rwx-w---x test/rwx-w--w- test/rwx-w--wx test/rwx-wx--- test/rwx-wx--x test/rwx-wx-w- test/rwx-wx-wx
こうやれば、持ち主しか読めないファイルをリストアップできるわけだ。
シンボル表記の場合
こっちのほうが難しい気がして後回しにしておいたんだけど。というか、俺はいままで使い方知らなかったんで避けてたんだけど、もしかして 8進数を知らない人にはこっちのほうが簡単なのかもしれない。
いや、でも書いているうちにやっぱりよくわかんなくなってきた。わかんなくなった顛末は後ろのほうに。
まず exactly matchの場合。chmodと同じく [augo]+[rwx] だ (ほんとは "s" とかも使えるんだろうけどここは解説しない)
[12:08]jargon:find-test<221> find test -perm a+r test/r--r--r-- [12:12]jargon:find-test<224> find test -perm o+r test/------r--
"-" や "+" もつかえる
[12:11]jargon:find-test<223> find test -perm -a+r | head test test/r--r--r-- test/r--r--r-x test/r--r--rw- test/r--r--rwx test/r--r-xr-- test/r--r-xr-x test/r--r-xrw- test/r--r-xrwx test/r--rw-r-- [12:11]jargon:find-test<222> find test -perm +a+r | tail test/rwxrw-rw- test/rwxrw-rwx test/rwxrwx--- test/rwxrwx--x test/rwxrwx-w- test/rwxrwx-wx test/rwxrwxr-- test/rwxrwxr-x test/rwxrwxrw- test/rwxrwxrwx
"a+r" とかで単純に指定できるのはいいが、それよりややこしいのはどうするのか? それには"," で区切ってつなげることができる:
[12:21]jargon:find-test<268> find test -perm g+w,u+r test/r---w----
無論、"-"とあわせてもつかえる。"r.x.wx..x" が立っているものだけ出ているのを確認してほしい:
[12:21]jargon:find-test<269> find test -perm -g+w,u+r,a+x |head test/r-x-wx--x test/r-x-wx-wx test/r-x-wxr-x test/r-x-wxrwx test/r-xrwx--x test/r-xrwx-wx test/r-xrwxr-x test/r-xrwxrwx test/rwx-wx--x test/rwx-wx-wx
もちろん "+"とも...あ、あれ??
[12:21]jargon:find-test<270> find test -perm +g+w,u+r,a+x | head test test/--------x test/-------w- test/-------wx test/------r-x test/------rw- test/------rwx test/-----x--- test/-----x--x test/-----x-w- [12:23]jargon:find-test<271> find test -perm +g+w,u+r,a+x | wc -l 509
なんか数多すぎ..
[12:23]jargon:find-test<273> find test -perm +g+w | head test test/-------w- test/-------wx test/------rw- test/------rwx test/-----x-w- test/-----x-wx test/-----xrw- test/-----xrwx test/----w----
えー、g+wが立ってなくても出てるじゃん。なんだこれ??えらそうに書いてきた俺の立場にもなってくれ。
もしかして find utilsのバグか?? 以下の二つは同じ結果を返すって man findには書いてあるんだが:
[12:24]jargon:find-test<275> find test -perm +022 |wc -l 384 [12:24]jargon:find-test<276> find test -perm +g+w,o+w | wc -l 449
ちなみに versionはこれ:
[12:24]jargon:find-test<277> find --version GNU find version 4.2.22 Features enabled: D_TYPE O_NOFOLLOW(enabled)
まとめ
もう、よくわからなくなったのでクソして寝る! といいたいが俺は朝クソ派なので、こんな時間にクソできないのであった。困ったものだ。
May the shit be with you!