在 RHEL 7 上使用 bash shell - 为什么当我不使用 -exec 时 find 会找到更多文件?

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

我正在寻找所有 setuid/setgid 文件。 当我不使用 -exec 时,它按预期工作:

# 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

当我使用 -exec 时,我只得到结果的一个子集:

# 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

为什么?

您只使用 -o 右侧的 -exec。因此,它被这样解析:

# What's actually happening
find /usr/bin '(' -type f -perm -4000 ')' -o '(' -perm -2000 -exec ls -l {} \; ')'

显然,这不是您想要的。


要使其适用于条件的两边,添加一些括号进行分组:

# What you want to happen
find /usr/bin -type f '(' -perm -4000 -o -perm -2000 ')' -exec ls -l {} +

原因是,如果您不指定明确的操作,find 假定 -print 作为默认操作。当您自己添加一个动作时,它会关闭该默认值,因此只有您明确指定动作的项目才会得到一个。

也就是说:

# 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

请注意最后一个,它暴露了默认行为中的一个警告:您可能希望 -type f 应用于 -o 的两侧,但如果没有明确分组,它会被放在左边,就像显式 -execprint 放在右边一样。

这个故事的寓意:在查找中使用 -o 时,请明确说明您的分组,除非您非常确定默认行为是您想要的。