如何正确范围GNU find的-or运算符?如何找到可执行文件的符号链接?

Jam*_* Ko 2 unix linux bash shell posix

我正在我的shell脚本中创建一个如下所示的函数:

getcmds()
{
    # find all executable files/symlinks in $(searchdirs) that start with 'upvoter-'
    searchdirs | xargs -i find {} -name 'upvoter-*' -type f -or -type l -maxdepth 1 -perm +111
}
Run Code Online (Sandbox Code Playgroud)

当我从我的脚本中的另一个位置运行此函数时,我得到了一大堆没有开头的输出upvoter-.我最终将其缩小到find这样解释我的查询的事实:

找到所有文件并以其开头upvoter-,OR是顶级目录中的可执行符号链接

我查看了查找手册页,试图找到解决问题的方法.我注意到find支持的括号,所以我尝试了这个:

find {} -name 'upvoter-*' -type f -or \( -type l \) -maxdepth 1 -perm +111
Run Code Online (Sandbox Code Playgroud)

还有这个:

find {} -name 'upvoter-*' \( -type f -or -type l \) -maxdepth 1 -perm +111
Run Code Online (Sandbox Code Playgroud)

不幸的是,他们都没有工作.我该怎么做才能解决这个问题?

谢谢.

mkl*_*nt0 5

为了补充Jonathan Leffler的有用答案和@ muru的helfpul评论:

  • 您问题中最后一个命令命令应该优先级方面起作用:

    • find隐式地结合试验-type操作-print-and(逻辑AND;所述符合POSIX标准的形式是-a).
      • 相比之下,-maxdepth是一个选项,它不是位置的,总是适用于整个命令.
      • 有关find术语和概念的概述,请参阅我的这个答案.
    • 您的上一个解决方案尝试正确使用括号来更改隐含的评估优先级,以实现所需的逻辑(-or优先级低于-and).
      • 与此相反,在你的括号第一个解决方案的尝试,-or \( -type l \)具有对优先没有任何影响,因为他们奉上只测试(而优先通过定义只事项操作数).
      • 注意如何(以及如何)引用它们\(以及\)保护它们免受shell的解释; '('并且')'也会工作.
  • 然而,-perm测试可能不会做你想要的它:因为写的,它测试符号链接自己为可执行,而不是他们的目标.鉴于符号链接始终标记为可执行文件,无论其目标是什么,您最终都会匹配任何符号链接,即使它没有引用可执行文件.

    • 要解决这个问题,请使用-L选项,这样可以find将测试应用于符号链接-perm目标.
      • 但请注意,有一个副作用:-Lfind遇到目录的符号链接时,它会进入该目录(即,它也会处理符号链接的目标目录),默认情况下不会发生这种情况.

通过上述考虑,有点讽刺的是,需要对括号消失干脆,因为\( -type f -or -type l \)可以只被替换-type f,因为-L现在确保一个符号链接目标的类型进行测试:

注意:
- 我已从{}以下命令中删除了find仅关注命令.如果没有filename参数,GNU会find隐式操作当前目录(.隐含); find相反,BSD 需要文件名参数.
- 此外,/111不是+111用作权限掩码,因为+语法在不久前已被弃用,实际上在GNU find4.5.12中删除.
- 最后,-maxdepth 1放在第一个位置元素(测试-name)之前,不仅为了更大的概念清晰度(如上所述-maxdepth,因为它是一个选项,总是适用于整个命令),而且还抑制警告,find否则最近版本的GNU 会问题.

find -L -maxdepth 1 -name 'upvoter-*' -type f -perm /111
Run Code Online (Sandbox Code Playgroud)

关于你的命令的其他想法:

  • -perm /111(-perm +111)应用任何指定位设置逻辑,即,它测试是否为任何安全主体设置了可执行位; 符号模式的等价物是-perm /a=x.
    • 如上所述,+语法不久前已弃用,并在GNU findv4.5.12中删除.
    • find相比之下,BSD仍然支持+,遗憾的是,没有任何具有此功能的命令可以与GNU find4.5.12或更高版本的两种实现一起使用.
    • 无论如何,此功能是非标准的(不符合POSIX).
  • 如果您只想匹配设置了所有执行位的文件,请使用prefix -:-perm -111-perm -a=x
  • 或者,如果您想测试文件是否可执行,使用-executable测试(GNU find扩展).
    • 此外,-executable"考虑了-perm测试忽略的访问控制列表和其他权限假象".(来自man find).

最后,GNU xargs-i选项已被弃用; 手册建议使用-I {}.