Unix查找:搜索可执行文件

时间:2010-12-16 06:40:27

标签: bash unix terminal find find-util

我可以在Unix find命令中使用哪种类型的参数/标志,以便搜索可执行文件?

10 个答案:

答案 0 :(得分:147)

在GNU版本的find上,您可以使用-executable

find . -type f -executable -print

对于BSD版本的find,您可以将-perm+和八进制掩码一起使用:

find . -type f -perm +111 -print

在此上下文中,“+”表示“任何这些位都置位”,111是执行位。

请注意,这与GNU find中的-executable谓词不同。特别是,-executable测试文件可以由当前用户执行,而-perm +111只测试是否设置了任何执行权限。

较旧版本的GNU find也支持-perm +111语法,但从4.5.12开始,不再支持此语法。相反,您可以使用-perm /111来获取此行为。

答案 1 :(得分:29)

向@ gniourf_gniourf提出澄清基本误解的提示。

此答案尝试提供概述现有答案,并讨论其细微之处相对优点以及提供背景信息,尤其是可移植性

查找可执行文件可以参考两个不同的用例

  • 以用户为中心:查找当前用户可执行的文件
  • 以文件为中心:查找包含(一个或多个) 可执行权限位 的文件。

请注意,在任一方案中,使用find -L ... 而不仅仅是find ...才有意义同时找到< em>符号链接到可执行文件

请注意,最简单的以文件为中心的案例 - 查找具有为所有三个安全主体(用户,组,其他)设置的可执行权限位的可执行文件 - 通常,但不一定产生与以用户为中心的场景相同的结果 - 理解差异非常重要。

以用户为中心(-executable

  • accepted answer值得推荐-executable,IF GNU find可用。

    • GNU find附带大多数 Linux 发行版
      • 相比之下,基于BSD的平台,包括macOS,都带有BSD find,功能不强。
    • 根据方案的要求,-executable仅匹配当前用户可以执行的文件(有边缘情况。 [1] )。
  • 接受的答案提供的 BSD find替代方法-perm +111 回答不同< / em>, file -centric question (正如答案本身所述)。

    • 仅使用-perm来回答用户中心问题是不可能 ,因为我们需要的是文件的用户和组标识与当前用户的相关联,而-perm只能测试文件的权限 仅使用POSIX find features,如果不涉及外部实用程序,则无法回答问题。
    • 因此,最佳-perm可以(单独)完成-executable近似 可能更接近近似值-perm +111 <{1}} ,以便找到为所有安全主体设置可执行位的文件(用户,组) ,其他) - 这让我觉得这是一个典型的现实场景。作为奖励,它也恰好符合POSIX(使用-perm -111包含符号链接,请参阅下面的解释):

      find -L
  • gniourf_gniourf's answer 使用find . -type f -perm -111 # or: find . -type f -perm -a=x 提供真实,可移植的等效-executable ,尽管 at绩效费用

    • -exec test -x {} \;-exec test -x {} \;结合使用(即,至少有一个可执行位集的文件)可以帮助提高性能{ {1}}不需要为每个文件调用(以下使用符合POSIX标准的BSD等效查找-perm +111 / GNU查找exec;请参见下文作为解释):

      -perm +111

以文件为中心(-perm /111

  • 回答文件中心问题 足以使用符合POSIX的find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print 主< / strong>(在GNU查找术语中称为 test )。
    • -perm允许您测试任何文件权限,而不仅仅是可执行性。
    • 权限指定为八进制符号模式。八进制模式是八进制数(例如,-perm),而符号模式是字符串(例如,-perm)。
    • 符号模式将安全主体标识为111(用户),a=x(组)和u(其他)或g指的是这三个。例如,权限表示为可执行文件的o,并使用运算符ax=分配给主体;对于完整讨论,包括八进制模式,请参阅the POSIX spec for the chmod utility
    • +的上下文中:
      • 使用- (例如,find)添加模式意味着:匹配 all 指定权限的文件(但匹配的文件可能有其他权限)。
      • 无前缀(例如-)表示:匹配具有此完整,完全权限集的文件。
      • 警告 GNU查找和BSD查找都会使用实施附加,非标准前缀 -any-of-specified-permission-bits-set logic ,但使用 不兼容的语法 执行此操作:
        • BSD查找:-ug=x
        • GNU find:755 [2]
      • 因此,如果您的代码必须可移植 ,请避免使用这些扩展程序。
  • 以下示例展示了各种以文件为中心的问题的便携式答案。

以文件为中心的命令示例

注意:

  • 以下示例符合POSIX标准,这意味着它们应该适用于任何POSIX兼容的实现,包括GNU find和BSD find;具体而言,这需要:
    • 不使用非标准模式前缀+/
    • 使用逻辑运算符原色的POSIX表单:
      • +表示NOT(GNU查找和BSD查找也允许/);请注意,示例中使用!以保护-not免受shell历史记录扩展的影响
      • \!用于AND(GNU查找和BSD查找也允许!
      • -a用于OR(GNU查找和BSD查找也允许-and
  • 这些示例使用符号模式,因为它们更易于阅读和记忆。
    • 使用模式前缀-o-or-运算符可以互换使用 (例如,=相当于+ - 除非您稍后申请-u=x,但这样做没有意义。)
    • 使用-u+x加入部分模式; AND逻辑暗示;例如,-x表示必须设置用户组可执行位。
    • 模式不能自己表达负匹配,而#34;仅当此位未设置时才匹配&#34 ;;您必须使用单独的,表达式与NOT primary -u=x,g=x
  • 请注意,找到原色(例如-perm!;也称为操作测试GNU find中的隐式-print(逻辑AND),-perm和可能的括号(转义为-a和{{实现OR逻辑需要1}} for shell。
  • -o而不仅仅是\(用于将符号链接与可执行文件相匹配
    • \)指示find评估符号链接的目标而不是符号链接本身;因此,如果没有find -L ...find ...将完全忽略符号链接。
-L

[1]从-L开始,-type f对GNU的描述发现4.4.2:

  

匹配可执行文件和可搜索的目录(在文件名解析意义上)。这考虑了访问权限             控制列表和其他权限人工制品 - -perm测试忽略。此测试使用access(2)系统调用,因此可以             被执行UID映射(或根压缩)的NFS服务器所欺骗,因为许多系统在客户端的内核中实现了访问(2),所以不能             利用服务器上保存的UID映射信息。因为此测试仅基于access(2)系统调用的结果,所以             不能保证实际执行此测试成功的文件。

[2] GNU查找版本早于4.5.12 也允许使用前缀# Match files that have ALL executable bits set - for ALL 3 security # principals (u (user), g (group), o (others)) and are therefore executable # by *anyone*. # This is the typical case, and applies to executables in _system_ locations # (e.g., /bin) and user-installed executables in _shared_ locations # (e.g., /usr/local/bin), for instance. find -L . -type f -perm -a=x # -a=x is the same as -ugo=x # The POSIX-compliant equivalent of `-perm +111` from the accepted answer: # Match files that have ANY executable bit set. # Note the need to group the permission tests using parentheses. find -L . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) # A somewhat contrived example to demonstrate the use of a multi-principial # mode (comma-separated clauses) and negation: # Match files that have _both_ the user and group executable bit set, while # also _not_ having the other executable bit set. find -L . -type f -perm -u=x,g=x \! -perm -o=x ,但这首先被弃用并最终删除,因为将-executableman find结合使用由于被解释为精确权限掩码,符号模式可能会产生意外结果。 如果你(a)在之前运行 4.5.12 并且(b)将自己限制在 octal 模式只有,你可以使用+两个 GNU find和BSD find,但这不是一个好主意。

答案 2 :(得分:9)

您可以使用-executable测试标记:

-executable
              Matches files which are executable  and  directories  which  are
              searchable  (in  a file name resolution sense).

答案 3 :(得分:8)

以便有另一种可能 1 来查找当前用户可执行的文件:

find . -type f -exec test -x {} \; -print

(这里的测试命令是在PATH中找到的,很可能是/usr/bin/test,而不是内置的。


1 仅在-executable的{​​{1}}标志不可用时才使用此项!这与find解决方案略有不同。

答案 4 :(得分:2)

这适用于我和想分享......

find ./ -type f -name "*" -not -name "*.o" -exec sh -c '
    case "$(head -n 1 "$1")" in
      ?ELF*) exit 0;;
      MZ*) exit 0;;
      #!*/ocamlrun*)exit0;;
    esac
exit 1
' sh {} \; -print

答案 5 :(得分:2)

find . -executable -type f

并不能保证文件是可执行的,它会找到设置了执行位的文件。如果你这样做

chmod a+x image.jpg

上面的发现会认为image.jpg是一个可执行文件,即使它实际上是一个设置了执行位的jpeg图像。

我通常会解决这个问题:

find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"

如果您希望find实际打印有关可执行文件的圆顶信息,您可以执行以下操作:

find . -type f -executable -printf "%i.%D %s %m %U %G %C@ %p" 2>/dev/null |while read LINE
do
  NAME=$(awk '{print $NF}' <<< $LINE)
  file -b $NAME |grep -qEw "executable|shared object|ELF|script|a\.out|ASCII text" && echo $LINE
done

在上面的示例中,文件的完整路径名在最后一个字段中,并且必须使用awk“NAME = $(awk'{print $ NF}'&lt;&lt;&lt;&lt; $ LINE)”来反映您查找的位置 如果文件名在查找输出字符串中的其他位置,则需要将“NF”替换为正确的数字位置。如果您的分隔符不是空格,您还需要告诉awk您的分隔符是什么。

答案 6 :(得分:1)

这是非常容易的荒谬 ...更不用说旁边不可能了。举起手来,我顺从Apple / Spotlight ......

mdfind 'kMDItemContentType=public.unix-executable'

至少它有效!

答案 7 :(得分:1)

简单的答案是:“您的可执行文件位于PATH变量中包含的目录中”,但是它实际上找不到您的可执行文件,并且可能会错过很多可执行文件。

我不太了解mac,但我认为“mdfind'kMDItemContentType = public.unix-executable'”可能会错过像解释脚本这样的东西

如果您可以找到设置了可执行位的文件(无论它们是否实际可执行),那么就可以了

find . -type f -perm +111 -print

支持“-executable”选项将进一步过滤查看acl和其他权限工件但技术上与“-pemr +111”没有太大区别。

也许将来find会支持“-magic”并让你明确查看具有特定魔法id的文件......但是你必须指定精确所有可执行格式的魔法id。

我不知道在unix上有一个技术上正确的简单方法。

答案 8 :(得分:0)

我有同样的问题,答案在dmenu source code:为此目的而制作的最佳实用程序。你可以编译&#39; stest.c&#39;和&#39; arg.h&#39;文件,它应该工作。有一个使用的手册页,我为方便起见放在那里:

STEST(1)         General Commands Manual         STEST(1)

NAME
       stest - filter a list of files by properties

SYNOPSIS
       stest  [-abcdefghlpqrsuwx]  [-n  file]  [-o  file]
       [file...]

DESCRIPTION
       stest takes a list of files  and  filters  by  the
       files'  properties,  analogous  to test(1).  Files
       which pass all tests are printed to stdout. If  no
       files are given, stest reads files from stdin.

OPTIONS
       -a     Test hidden files.

       -b     Test that files are block specials.

       -c     Test that files are character specials.

       -d     Test that files are directories.

       -e     Test that files exist.

       -f     Test that files are regular files.

       -g     Test  that  files  have  their set-group-ID
              flag set.

       -h     Test that files are symbolic links.

       -l     Test the contents of a directory  given  as
              an argument.

       -n file
              Test that files are newer than file.

       -o file
              Test that files are older than file.

       -p     Test that files are named pipes.

       -q     No  files are printed, only the exit status
              is returned.

       -r     Test that files are readable.

       -s     Test that files are not empty.

       -u     Test that files have their set-user-ID flag
              set.

       -v     Invert  the  sense  of  tests, only failing
              files pass.

       -w     Test that files are writable.

       -x     Test that files are executable.

EXIT STATUS
       0      At least one file passed all tests.

       1      No files passed all tests.

       2      An error occurred.

SEE ALSO
       dmenu(1), test(1)

                        dmenu-4.6                STEST(1)

答案 9 :(得分:0)

因此,如果您实际上想查找可执行文件类型(例如脚本,ELF二进制文件等。等等),而不仅是具有执行权限 permission 的文件,那么您可能想做更多类似的事情(当前目录。可以替换为所需的任何目录):

 gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

或者对于那些不使用macports(Linux用户)或以其他方式安装gnu find的用户:

 find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

尽管如果您使用的是OS X,则它隐藏了一个名为is_exec的小工具,该工具基本上为您捆绑了该小测试,因此,如果找到它,则可以缩短命令行。但是这种方式更加灵活,因为您可以轻松地将==测试替换为=〜测试,并使用它来检查更复杂的属性,例如可执行的纯文本文件或file命令返回的任何其他信息。


这里引用的确切规则非常模糊,因此我最终还是通过反复试验得出结论,但是我很想听听正确的解释。