I'm looking for all setuid/setgid files.
When I don't use -exec
, it works as expected:
# find /usr/bin -type f -perm -4000 -o -perm -2000
/usr/bin/wall
/usr/bin/ksu
/usr/bin/chage
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/fusermount
/usr/bin/passwd
/usr/bin/write
/usr/bin/su
/usr/bin/umount
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/pkexec
/usr/bin/crontab
/usr/bin/cgclassify
/usr/bin/cgexec
/usr/bin/ssh-agent
/usr/bin/Xorg
/usr/bin/at
/usr/bin/sudo
/usr/bin/locate
/usr/bin/staprun
When I use -exec
, I only get a subset of the results back:
# find /usr/bin -type f -perm -4000 -o -perm -2000 -exec ls -l {} \;
-r-xr-sr-x. 1 root tty 15344 Jan 27 2014 /usr/bin/wall
-rwxr-sr-x. 1 root tty 19536 Aug 21 2015 /usr/bin/write
-rwxr-sr-x. 1 root cgred 15624 Sep 21 2014 /usr/bin/cgclassify
-rwxr-sr-x. 1 root cgred 15584 Sep 21 2014 /usr/bin/cgexec
---x--s--x. 1 root nobody 306304 Sep 24 2015 /usr/bin/ssh-agent
-rwx--s--x. 1 root slocate 40504 Jan 26 2014 /usr/bin/locate
Why?
You're only using -exec
on the right-hand side of the -o
. Thus, it's being parsed like this:
# What's actually happening
find /usr/bin '(' -type f -perm -4000 ')' -o '(' -perm -2000 -exec ls -l {} \; ')'
Obviously, that's not what you want.
To make it apply to both sides of the conditional, add some parens for grouping:
# What you want to happen
find /usr/bin -type f '(' -perm -4000 -o -perm -2000 ')' -exec ls -l {} +
The reason is that if you don't specify an explicit action, find
assumes a -print
as the default action. When you add an action yourself it turns off that default, so only the items for which you explicitly specify an action get one.
That is to say:
# These commands are all equivalent:
find /usr/bin -type f -perm -4000 -o -perm -2000
find /usr/bin '(' -type f -perm -4000 -o -perm -2000 ')' -print
find /usr/bin '(' '(' -type f -perm -4000 ')' -o '(' -perm -2000 ')' ')' -print
Note that last one, which exposes a caveat in the default behavior: You probably wanted the -type f
to apply to both sides of the -o
, but without explicit grouping it gets put on the left, just as an explicit -exec
or print
gets put on the right.
Moral of this story: When using -o
in find, be explicit about your grouping unless you're very certain that the default behavior is what you want.