I want to find files that a particular user will not be able to read.
Assume the username is "user123" and they are in a group called "user123". I want to find files that, if they are owned by user123 have u+r on; failing that if the file is group user123 it should have g+r on; failing that it can have o+r on.
Since GNU find has "-readable", I could do this:
sudo -u user123 find /start ! -readable -ls
However the process has to run by a user that does not have sudo access. Therefore I I tried this: (it doesn't check o+r but that isn't important at this point)
find /start \( -user user123 ! -perm -u=r \) -o \( -group user123 ! -perm -g=r \) -ls
but it lists this file:
272118 4 -rw------- 1 user123 user123 3243 Jul 3 19:50 /start/blah/blah/file.txt
This file is the only file under /start
that is owned by user123 with g=r
off. It is as if find is interpreting the -u=r
as -g=r
.
I decided to try reversing the logic and instead test not ( truth )
instead:
find /etc/puppet ! \( \( -user puppet -perm -u=r \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \) -ls
That works!
Why did the original find
fail? Is it a bug in find
(unlikely) or is the logic wrong?
Update: I had the logic wrong. As pointed out below, since ! ( A || B || C ) == ( !A && !B && !C ) these are the two equivalent statements:
find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls
My goal was not to have to test user/group twice. What I really need is a more complicated if-then-else structure, which would probably only be possible if there was an -xor operator. I could build an xor out of and/or/not but it would be more complex than the two solutions above.
puppet
has access to a file with--wxrwxrwx puppet puppet
. – Stéphane Chazelas Aug 28 '13 at 19:50