bash 使用 find 命令搜索可执行文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4458120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Search for executable files using find command
提问by well actually
What type of parameter/flag can I use with the Unix find
command so that I search executables?
我可以在 Unixfind
命令中使用什么类型的参数/标志来搜索可执行文件?
回答by Laurence Gonsalves
On GNU versions of find you can use -executable
:
在 GNU 版本的 find 上,您可以使用-executable
:
find . -type f -executable -print
For BSD versions of find, you can use -perm
with +
and an octal mask:
对于 BSD 版本的 find,您可以使用-perm
with+
和一个八进制掩码:
find . -type f -perm +111 -print
In this context "+" means "any of these bits are set" and 111 is the execute bits.
在这种情况下,“+”表示“设置了这些位中的任何一个”,而 111 是执行位。
Note that this is not identical to the -executable
predicate in GNU find. In particular, -executable
tests that the file can be executed by the current user, while -perm +111
just tests if any execute permissions are set.
请注意,这与-executable
GNU find 中的谓词不同。特别是,-executable
测试当前用户可以执行该文件,而-perm +111
只测试是否设置了任何执行权限。
Older versions of GNU find also support the -perm +111
syntax, but as of 4.5.12this syntax is no longer supported. Instead, you can use -perm /111
to get this behavior.
旧版本的 GNU find 也支持该-perm +111
语法,但从4.5.12 开始不再支持该语法。相反,您可以使用-perm /111
来获取此行为。
回答by mklement0
Tip of the hat to @gniourf_gniourffor clearing up a fundamental misconception.
尖帽子@的gniourf_gniourf清除了一个根本性的误解。
This answer attempts to provide an overview of the existing answersand to discuss their subtletiesand relative meritsas well as to provide background information, especially with respect to portability.
此答案试图提供现有答案的概述,并讨论它们的微妙之处和相对优点,并提供背景信息,尤其是在可移植性方面。
Finding files that are executable can refer to two distinct use cases:
查找可执行文件可以指两个不同的用例:
- user-centric: find files that are executable by the current user.
- file-centric: find files that have (one or more) executable permission bitsset.
- 以用户为中心:查找当前用户可执行的文件。
- 以文件为中心:发现有文件(一个或多个)可执行权限位集。
Note that in eitherscenario it may make sense to use find -L ...
instead of just find ...
in order to also find symlinks toexecutables.
请注意,在这两种情况下,使用find -L ...
而不是仅仅find ...
为了找到指向可执行文件的符号链接可能是有意义的。
Note that the simplest file-centric case - looking for executables with the executable permissions bit set for ALL three security principals (user, group, other) - will typically, but not necessarilyyield the same results as the user-centric scenario - and it's important to understand the difference.
请注意,最简单的以文件为中心的情况——寻找为所有三个安全主体(用户、组、其他)设置了可执行权限位的可执行文件——通常,但不一定会产生与以用户为中心的场景相同的结果——它是了解差异很重要。
User-centric (-executable
)
以用户为中心 ( -executable
)
The accepted answercommendably recommends
-executable
, IF GNUfind
is available.- GNU
find
comes with most Linuxdistros- By contrast, BSD-based platforms, including macOS, come with BSD find, which is less powerful.
- As the scenario demands,
-executable
matches only files the current usercan execute (there are edge cases.[1]).
- GNU
The BSD
find
alternative offered by the accepted answer (-perm +111
)answers a different, file-centric question(as the answer itself states).- Using just
-perm
to answer the user-centric question is impossible, because what is needed is to relatethe file'suser and group identity to the current user's, whereas-perm
can only test the file'spermissions.
Using only POSIXfind
features, the question cannot be answered without involving external utilities. Thus, the best
-perm
can do (by itself) is an approximationof-executable
. Perhaps a closerapproximation 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 (usefind -L
to include symlinks, see farther below for an explanation):find . -type f -perm -111 # or: find . -type f -perm -a=x
- Using just
gniourf_gniourf's answerprovides 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 oneexecutable bit set) may help performance in thatexec
needn't be invoked for everyfile (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
该接受的答案值得称赞的建议
-executable
,IF GNUfind
是可用的。- GNU
find
随大多数Linux发行版一起提供- 相比之下,基于 BSD 的平台(包括 macOS)带有 BSD find,但功能较弱。
- 根据场景要求,
-executable
仅匹配当前用户可以执行的文件(存在边缘情况。[1])。
- GNU
接受的答案 ( )提供的BSD
find
替代方案-perm +111
回答了一个不同的、以文件为中心的问题(正如答案本身所述)。- 只需使用
-perm
回答用户-centric问题是不可能的,因为我们需要的是对有关该文件的用户和组身份给当前用户的,而-perm
只能测试文件的权限。
仅使用POSIXfind
features,如果不涉及外部实用程序就无法回答这个问题。 因此,最好
-perm
能(本身)做的是一个近似的-executable
。也许比is更接近-perm +111
-perm -111
,以便找到为所有安全主体(用户、组、其他)设置了可执行位的文件 - 这让我觉得这是典型的现实世界场景。作为奖励,它也恰好是 POSIX 兼容的(用于find -L
包含符号链接,请参阅下面的更多解释):find . -type f -perm -111 # or: find . -type f -perm -a=x
- 只需使用
gniourf_gniourf 的回答提供了一个真正的、可移植的等价物
-executable
, using-exec test -x {} \;
,尽管以牺牲性能为代价。结合
-exec test -x {} \;
使用-perm +111
(即,具有至少一个可执行位集的文件)可能有助于提高性能,因为exec
不需要为每个文件调用(以下使用符合 POSIX 的 BSD find-perm +111
/ GNU find等价物-perm /111
;有关解释,请参见下文) :find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
File-centric (-perm
)
以文件为中心 ( -perm
)
- To answer file-centric questions, it issufficient to use the POSIX-compliant
-perm
primary(known as a testin GNU find terminology).-perm
allows you to test for anyfile permissions, not just executability.- Permissions are specified as either octalor symbolic modes. Octal modes are octal numbers (e.g.,
111
), whereas symbolic modes are strings (e.g.,a=x
). - Symbolic modesidentify the security principals as
u
(user),g
(group) ando
(other), ora
to refer to all three. Permissions are expressed asx
for executable, for instance, and assigned to principals using operators=
,+
and-
; for a full discussion, including of octal modes, see the POSIX spec for thechmod
utility. - In the context of
find
:- Prefixing a mode with
-
(e.g.,-ug=x
) means: match files that have allthe permissions specified(but matching files may have additional permissions). - Having NO prefix(e.g.
755
) means: match files that have this full, exactset of permissions. - Caveat: Both GNU find and BSD findimplement an additional, nonstandardprefixwith are-ANY-of-the-specified-permission-bits-set logic, but do so with incompatible syntax:
- BSD find:
+
- GNU find:
/
[2]
- BSD find:
- Therefore, avoid these extensions, if your code must be portable.
- Prefixing a mode with
- The examples below demonstrate portable answers to various file-centric questions.
- 要回答以文件为中心的问题,使用符合 POSIX 的主要(在 GNU 查找术语中称为测试)就足够了
-perm
。-perm
允许您测试任何文件权限,而不仅仅是可执行性。- 权限被指定为八进制或符号模式。八进制模式是八进制数(例如,
111
),而符号模式是字符串(例如,a=x
)。 - 符号模式将安全主体标识为
u
(用户)、g
(组)和o
(其他),或a
指代所有三者。x
例如,权限表示为可执行文件,并使用运算符=
、+
和-
;分配给主体。有关包括八进制模式在内的完整讨论,请参阅实用程序的 POSIX 规范chmod
。 - 在以下情况下
find
:- 以
-
(例如,-ug=x
)为模式前缀意味着:匹配具有指定所有权限的文件(但匹配的文件可能具有额外的权限)。 - 有没有前缀(如
755
)是指:具有此匹配的文件完整,准确的权限。 - 警告:GNU find 和 BSD find都使用are-ANY-of-the-specified-permission-bits-set logic实现了一个额外的非标准前缀,但这样做的语法不兼容:
- BSD 发现:
+
- GNU 发现:
/
[2]
- BSD 发现:
- 因此,如果您的代码必须是可移植的,请避免使用这些扩展。
- 以
- 下面的示例演示了各种以文件为中心的问题的可移植答案。
File-centric command examples
以文件为中心的命令示例
Note:
笔记:
- The following examples are POSIX-compliant, meaning they should work in any POSIX-compatible implementation, including GNU find and BSD find; specifically, this requires:
- NOT using nonstandard mode prefixes
+
or/
. - Using the POSIX forms of the logical-operator primaries:
!
for NOT (GNU find and BSD find also allow-not
); note that\!
is used in the examples so as to protect!
from shell history expansions-a
for AND (GNU find and BSD find also allow-and
)-o
for OR (GNU find and BSD find also allow-or
)
- NOT using nonstandard mode prefixes
- The examples use symbolicmodes, because they're easier to read and remember.
- With mode prefix
-
, the=
and+
operators can be used interchangeably (e.g.,-u=x
is equivalent to-u+x
- unless you apply-x
later, but there's no point in doing that). - Use
,
to join partial modes; AND logic is implied; e.g.,-u=x,g=x
means that both the user andthe group executable bit must be set. - Modes cannot themselvesexpress negative matching in the sense of "match only if this bit is NOT set"; you must use a separate
-perm
expression with the NOT primary,!
.
- With mode prefix
- Note that find's primaries(such as
-print
, or-perm
; also known as actionsand testsin GNU find) are implicitlyjoined with-a
(logical AND), and that-o
and possibly parentheses (escaped as\(
and\)
for the shell) are needed to implement OR logic. find -L ...
instead of justfind ...
is used in order to also match symlinks toexecutables-L
instructs find to evaluate the targetsof symlinks instead of the symlinks themselves; therefore, without-L
,-type f
would ignore symlinks altogether.
- 以下示例符合 POSIX 标准,这意味着它们应该适用于任何兼容 POSIX 的实现,包括 GNU find 和 BSD find;具体来说,这需要:
- 不使用非标准模式前缀
+
或/
. - 使用逻辑运算符原语的 POSIX 形式:
!
对于 NOT(GNU find 和 BSD find 也允许-not
);请注意,\!
在示例中使用它是为了防止!
shell 历史扩展-a
对于 AND(GNU find 和 BSD find 也允许-and
)-o
用于 OR(GNU 查找和 BSD 查找也允许-or
)
- 不使用非标准模式前缀
- 这些示例使用符号模式,因为它们更易于阅读和记忆。
- 使用 mode prefix
-
,=
and+
运算符可以互换使用(例如,-u=x
等效于-u+x
- 除非您-x
稍后申请,但这样做没有意义)。 - 使用
,
加入部分模式; AND 逻辑是隐含的;例如,-u=x,g=x
意味着必须设置用户和组可执行位。 - 模式本身不能表达“仅在未设置此位时才匹配”的意义上的否定匹配;您必须使用
-perm
带有 NOT 主要的单独表达式,!
.
- 使用 mode prefix
- 需要注意的是发现的初选(如
-print
,或-perm
;也被称为行动和测试在GNU发现)的隐含与加盟-a
(逻辑与),以及-o
和可能的括号(转义为\(
和\)
的壳),需要执行或逻辑。 find -L ...
而不仅仅是find ...
用于将符号链接匹配到可执行文件-L
指示 find 评估符号链接的目标而不是符号链接本身;因此,没有-L
,-type f
将完全忽略符号链接。
# 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] Description of -executable
from man find
as of GNU find 4.4.2:
[1]-executable
来自man find
GNU find 4.4.2 的描述:
Matches files which are executable and directories which are searchable (in a file name resolution sense). This takes into account access control lists and other permissions artefacts which the -perm test ignores. This test makes use of the access(2) system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing), since many systems implement access(2) in the client's kernel and so cannot make use of the UID mapping information held on the server. Because this test is based only on the result of the access(2) system call, there is no guarantee that a file for which this test succeeds can actually be executed.
匹配可执行文件和可搜索目录(在文件名解析意义上)。这考虑了 -perm 测试忽略的访问控制列表和其他权限人工制品。该测试使用了 access(2) 系统调用,因此可能会被执行 UID 映射(或根压缩)的 NFS 服务器所欺骗,因为许多系统在客户端内核中实现了 access(2),因此无法使用服务器上保存的 UID 映射信息。由于此测试仅基于 access(2) 系统调用的结果,因此无法保证此测试成功的文件确实可以执行。
[2] GNU find versions older than 4.5.12also allowed prefix +
, but this was first deprecated and eventually removed, because combining +
with symbolicmodes yields likely yields unexpected results due to being interpreted as an exactpermissions mask. Ifyou (a) run on a version before4.5.12 and(b) restrict yourself to octalmodes only, you couldget away with using +
with bothGNU find and BSD find, but it's not a good idea.
[2]早于 4.5.12 的GNU find 版本也允许使用 prefix +
,但这首先被弃用并最终被删除,因为+
与符号模式结合可能会产生意外结果,因为被解释为精确的权限掩码。如果您(a)在版本上运行之前4.5.12和(二)限制自己八进制模式而已,你可以摆脱使用+
与这两个GNU发现和BSD的发现,但它不是一个好主意。
回答by gniourf_gniourf
So as to have another possibility1to find the files that are executable by the current user:
以便有另一种可能性1找到当前用户可执行的文件:
find . -type f -exec test -x {} \; -print
(the test command here is the one found in PATH, very likely /usr/bin/test
, not the builtin).
(这里的测试命令是在 PATH 中找到的,很可能是/usr/bin/test
,而不是内置命令)。
1Only use this if the -executable
flag of find
is not available! this is subtly different from the -perm +111
solution.
1只有在-executable
标志find
不可用时才使用它!这与-perm +111
解决方案略有不同。
回答by codaddict
You can use the -executable
test flag:
您可以使用-executable
测试标志:
-executable
Matches files which are executable and directories which are
searchable (in a file name resolution sense).
回答by AjayKumarBasuthkar
This worked for me & thought of sharing...
这对我有用并想分享...
find ./ -type f -name "*" -not -name "*.o" -exec sh -c '
case "$(head -n 1 "")" in
?ELF*) exit 0;;
MZ*) exit 0;;
#!*/ocamlrun*)exit0;;
esac
exit 1
' sh {} \; -print
回答by louigi600
find . -executable -type f
does not really guarantee that the file is executable it will find files with the execution bit set. If you do
并不能真正保证文件是可执行的,它会找到设置了执行位的文件。如果你这样做
chmod a+x image.jpg
the above find will think image.jpg is an executable even if it is really a jpeg image with the execution bit set.
上面的 find 会认为 image.jpg 是一个可执行文件,即使它确实是一个设置了执行位的 jpeg 图像。
I generally work around the issue with this:
我通常解决这个问题:
find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"
If you want the find to actually print dome information about executable files you can do something like this:
如果您希望 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
In the above example the file's full pathname is in the last field and must reflect where you look for it with awk "NAME=$(awk '{print $NF}' <<< $LINE)" if the file name was elsewhere in the find output string you need to replace "NF" with the correct numerical position. If your separator is not space you also need to tell awk what your separator is.
在上面的示例中,文件的完整路径名位于最后一个字段中,并且如果文件名位于其他位置,则必须使用 awk "NAME=$(awk '{print $NF}' <<< $LINE)"您需要用正确的数字位置替换“NF”的查找输出字符串。如果您的分隔符不是空格,您还需要告诉 awk 您的分隔符是什么。
回答by louigi600
Well the easy answer would be: "your executable files are in the directories contained in your PATH variable" but that would not really find your executables and could miss a lot of executables anyway.
好吧,简单的答案是:“您的可执行文件位于 PATH 变量中包含的目录中”,但这不会真正找到您的可执行文件,并且无论如何都可能会错过很多可执行文件。
I don't know much about mac but I think "mdfind 'kMDItemContentType=public.unix-executable'" might miss stuff like interpreted scripts
我对 mac 不太了解,但我认为“mdfind 'kMDItemContentType=public.unix-executable'”可能会错过解释脚本之类的东西
If it's ok for you to find files with the executable bits set (regardless of whether they are actually executable) then it's fine to do
如果您可以找到设置了可执行位的文件(无论它们是否实际可执行),那么就可以了
find . -type f -perm +111 -print
where supported the "-executable" option will make a further filter looking at acl and other permission artifacts but is technically not much different to "-pemr +111".
支持“-executable”选项将进一步过滤查看 acl 和其他权限工件,但在技术上与“-pemr +111”没有太大区别。
Maybe in the future find will support "-magic " and let you look explicitly for files with a specific magic id ... but then you would haveto specify to fine all the executable formats magic id.
也许将来 find 将支持“-magic”并让您明确查找具有特定魔术 ID 的文件……但是您必须指定对所有可执行格式魔术 ID 进行细化。
I'm unaware of a technically correct easy way out on unix.
我不知道在 unix 上有一种技术上正确的简单方法。
回答by Alex Gray
It is SO ridiculousthat this is not super-easy... let alone next to impossible. Hands up, I defer to Apple/Spotlight...
这太荒谬了,这不是超级容易……更不用说几乎不可能了。举起手来,我听从 Apple/Spotlight...
mdfind 'kMDItemContentType=public.unix-executable'
mdfind 'kMDItemContentType=public.unix-executable'
At least it works!
至少它有效!
回答by Peter Gerdes
So if you actually want to find executable file types (e.g. scripts, ELF binaries etc.. etc..) not merely files with execution permissionthen you probably want to do something more like this (where the current directory . can be replaced with whatever directory you want):
因此,如果您实际上想要查找可执行文件类型(例如脚本、ELF 二进制文件等),而不仅仅是具有执行权限的文件,那么您可能想要做更多类似的事情(当前目录 . 可以替换为任何你想要的目录):
gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Or for those of you who aren't using macports (linux users) or otherwise have gnu find installed as find you want:
或者对于那些不使用 macports(linux 用户)或以其他方式安装 gnu find 的人来说:
find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Though if you are on OS X it comes with a little utility hidden somewhere called is_exec that basically bundles up that little test for you so you can shorten the command line if you find it. But this way is more flexible as you can easily replace the == test with the =~ test and use it to check for more complex properties like executable plain text files or whatever other info your file command returns.
尽管如果您使用的是 OS X,它会带有一个隐藏在某处的小实用程序,称为 is_exec,它基本上为您捆绑了该小测试,因此您可以在找到它时缩短命令行。但这种方式更灵活,因为您可以轻松地将 == 测试替换为 =~ 测试,并使用它来检查更复杂的属性,例如可执行纯文本文件或文件命令返回的任何其他信息。
The exact rules for quotation here are pretty opaque so I just end up working it out by trial and error but I'd love to hear the right explanation.
这里引用的确切规则非常不透明,所以我只是通过反复试验来解决它,但我很想听到正确的解释。
回答by Josuah Demangeon
I had the same issue, and the answer was in the dmenu source code: the stest utility made for that purpose. You can compile the 'stest.c' and 'arg.h' files and it should work. There is a man page for the usage, that I put there for convenience:
我遇到了同样的问题,答案在dmenu 源代码中:为此目的而制作的 stest 实用程序。您可以编译 'stest.c' 和 'arg.h' 文件,它应该可以工作。有一个使用手册页,为了方便起见,我把它放在那里:
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)