Using bash shell on RHEL 7 - why does find find more files when I don't use -exec?

141 Views Asked by At

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?

1

There are 1 best solutions below

0
On BEST ANSWER

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.