我可以使用什么类型的参数/标志与Unix find
命令一起使用,以便搜索可执行文件?
-executable
参数:find . -type f -executable -print
对于BSD版本的find命令,你可以使用-perm
和一个八进制掩码+
:
find . -type f -perm +111 -print
-L
选项:find -L ...
。 - mklement0-perm +111
可能会产生“误报”,即当前用户实际上无法执行的文件。仅通过测试权限无法模拟-executable
,因为需要将文件的用户和组标识与当前用户的标识相对应。 - mklement0find . -type f -perm +111 -print
是find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \)
。 - mklement0致敬 @gniourf_gniourf,感谢他澄清了一个基本误解。
本回答试图提供现有回答的概述,并讨论它们的微妙之处和相对优点,以及提供背景信息,特别是关于可移植性方面。
查找可执行文件可以涉及两个不同的用例:
请注意,在任何一个场景中,使用find -L ...
而不仅仅是find ...
可能是有意义的,以便还可以查找到指向可执行文件的符号链接。
-executable
)
The accepted answer commendably recommends -executable
, IF GNU find
is available.
find
comes with most Linux distros
-executable
matches only files the current user can execute (there are edge cases.[1]).The BSD find
alternative offered by the accepted answer (-perm +111
) answers a different, file-centric question (as the answer itself states).
-perm
to answer the user-centric question is impossible, because what is needed is to relate the file's user and group identity to the current user's, whereas -perm
can only test the file's permissions.find
features, the question cannot be answered without involving external utilities.Thus, the best -perm
can do (by itself) is an approximation of -executable
. Perhaps a closer approximation than -perm +111
is -perm -111
, so as to find files that have the executable bit set for ALL security principals (user, group, other) - this strikes me as the typical real-world scenario. As a bonus, it also happens to be POSIX-compliant (use find -L
to include symlinks, see farther below for an explanation):
find . -type f -perm -111 # or: find . -type f -perm -a=x
gniourf_gniourf's answer provides a true, portable equivalent of -executable
, using -exec test -x {} \;
, albeit at the expense of performance.
Combining -exec test -x {} \;
with -perm +111
(i.e., files with at least one executable bit set) may help performance in that exec
needn't be invoked for every file (the following uses the POSIX-compliant equivalent of BSD find -perm +111
/ GNU find -perm /111
; see farther below for an explanation):
find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
-perm
)-perm
主命令就足够了(在GNU find术语中称为“测试”)。
-perm
允许您测试任何文件权限,而不仅仅是可执行性。111
),而符号模式是字符串(例如a=x
)。u
(用户)、g
(组)和o
(其他),或者a
表示所有三个。权限用=
、+
和-
运算符分配给主体;有关完整讨论,包括八进制模式,请参见chmod实用程序的POSIX规范。find
的上下文中:
-
(例如-ug=x
)表示:匹配具有全部指定权限的文件(但匹配的文件可能具有其他权限)。755
)表示:匹配具有这个完整、精确权限集的文件。+
/
[2]以文件为中心的命令示例
注意:
The following examples are POSIX-compliant, meaning they should work in any POSIX-compatible implementation, including GNU find and BSD find; specifically, this requires:# 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
[1] GNU find 4.4.2 中 -executable
的描述:
匹配可执行文件和可搜索的目录(在文件名解析意义上)。这将考虑访问控制列表和其他权限工件,而
-perm
测试会忽略它们。此测试使用access(2)
系统调用,因此可能会被 NFS 服务器欺骗,因为许多系统在客户端内核中实现access(2)
,无法利用服务器上保存的 UID 映射信息。由于此测试仅基于access(2)
系统调用的结果,因此不能保证此测试成功的文件实际上可以被执行。
[2] GNU find版本早于4.5.12也允许前缀+
,但是这个功能已经被弃用并最终删除,因为将+
与符号模式组合可能会产生意外的结果,因为它被解释为一个精确的权限掩码。如果您(a)运行在之前4.5.12版本,并且(b)只限于使用八进制模式,那么您可以在GNU find和BSD find中同时使用+
,但这不是个好主意。
为了有另一种可能性1找到当前用户可执行的文件:
find . -type f -exec test -x {} \; -print
这里使用的测试命令是在PATH中找到的那个,很可能是 /usr/bin/test
,而不是内建的。
1 仅在 find
的 -executable
标志不可用时使用!这与 -perm +111
解决方案略有不同。
'{}'
或者 \{\}
。 - Ionoclast Brighamfind . -type f -perm -u=x
不是-executable
的等价物:-executable
匹配用户可以执行的所有文件,包括g+x
(如果我在适当的组中)或o+x
。实际上,-perm -u=x
会找到许多用户无法执行的文件,并错过一些用户可以执行的文件。” - mklement0{}
是一种假设性的必要性(并且引用不会有害),但在实践中,在类 POSIX 的 shell 和 csh
中并不需要。你知道哪些需要这样做的 shell 吗? - mklement0:)
。 - gniourf_gniourffish
中,{}
必须被转义为 '{}'
或 \{\}
。注意,bash
、ksh
和 zsh
都提供了同样类型的花括号扩展;然而,它们会原样打印未引用的标记 {}
(因此不需要转义),因为它们不认为这是一个有效的花括号表达式(它们至少需要两个标记或有效的数字序列表达式),而 fish
则将 {}
视为产生空字符串的有效花括号表达式。 - mklement0你可以使用-executable
测试标志:
-executable
Matches files which are executable and directories which are
searchable (in a file name resolution sense).
find . -executable -type f
这并不真正保证文件可执行,它只是查找具有执行位设置的文件。如果您想要
chmod a+x image.jpg
上面的`find`命令会认为`image.jpg`是一个可执行文件,即使它实际上只是一张带有执行权限的JPEG图像。
通常我会通过以下方式解决这个问题:
find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"
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
这对我有用,想要分享...
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
find ./ -mime application/x-sharedlib -o -mime application/x-dosexec
。 - Daniel Alder如果您想查找可执行文件类型(例如脚本、ELF二进制文件等等),而不仅仅是具有执行权限的文件,那么您可能需要执行类似以下命令的操作(其中当前目录“.”可以替换为您想要的任何目录):
find . -type f -executable
这将返回在指定目录中所有可执行文件的列表。
gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
如果您没有使用macports(Linux用户)或以其他方式安装了GNU find,您需要使用以下命令:
最初的回答:
find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
find . -type f -execdir sh -c "file -b {} | grep -q executable" \; -execdir realpath {} +
命令可以让你改变 realpath
,以便对可执行文件进行操作。请注意,这不适用于 可能 是可执行文件的文件,例如 .sh
空文件。 - Pablo Bianchi我遇到了同样的问题,答案在 dmenu源代码 中:为此而制作的stest实用程序。您可以编译'stest.c'和'arg.h'文件,然后它应该可以工作。有一个用法的man页面,我把它放在那里方便查看:
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)
find . -type f -perm +111 -print
如果支持,"-executable"选项将进一步过滤查看acl和其他权限工件,但在技术上与"-pemr +111"没有太大区别。
也许将来find会支持"-magic",并允许您明确查找具有特定魔术ID的文件...但那时您将不得不指定要查找所有可执行格式的魔术ID。
我不知道在Unix上是否有一个技术上正确且简单的解决方法。
mdfind 'kMDItemContentType=public.unix-executable'
至少这个方法有效!mdfind
是很好的。请注意,您的命令将报告整个系统的Unix可执行文件。mdfind -onlyin . 'kMDItemContentType=public.unix-executable'
将结果限制为当前目录的子树。有趣的细节:似乎不支持将搜索限制为仅特定目录(不包括子文件夹)。符号链接到可执行文件显然永远不会被包含。奇怪的是,一旦mdfind
已经发现文件是可执行的,后来_删除_可执行位不会被检测到。 - mklement0mdfind -onlyin . 'kMDItemContentType=public.unix-executable'
的行为类似于 find . -type f -perm +111 -print
。也就是说,它会找到任何可执行位设置的文件,这可能会产生误报(尽管在实践中可能不是问题)- 要想真正只查找当前用户可执行的文件,请参见 @gniourf_gniourf 的答案。使用基于 find
的解决方案的优点是,如果需要(选项 -L
),您可以找到指向可执行文件的符号链接,而 mdfind
似乎无法做到这一点。 - mklement0ls /Applications/**/*(*)
在你(我的?)zsh
shell 中。 - Alex Grayzsh
提示 - 我之前不知道; (似乎您可以匹配可执行文件(*
)或符号链接(@
),但不能同时匹配,对吗?)。至于您最初的观点:让我重申:find . -type f -perm +a=x
将执行您的mdfind
命令所做的操作,同时提供更多的灵活性。您甚至可以重新制定它以符合POSIX标准。 - mklement0
find -executable
... 但这并不能保证列出的每个文件都能真正执行。 - Williamfind
实现都是相同的。@sje397和@William推荐的选项可能不可用。最好使用下面显示的被接受的解决方案。 - Mr. Lance E Sloanfile
命令,即file $FILEPATH | grep -q executable
,如果$FILEPATH
看起来像一个可执行文件,则返回 true。这是一个很棒的小命令,虽然我不确定它有多常见(在 macOS 上预装)。确保你的file
命令是最新的,以便它可以正确检测大多数 shebangs。 - tmillr