我可以在Unix find
命令中使用哪种类型的参数/标志,以便搜索可执行文件?
find -executable
...但是这不能保证列出的每个文件都会真正执行
我可以在Unix find
命令中使用哪种类型的参数/标志,以便搜索可执行文件?
find -executable
...但是这不能保证列出的每个文件都会真正执行
Answers:
在GNU版本的find上,您可以使用-executable
:
find . -type f -executable -print
对于find的BSD版本,可以-perm
与+
和八进制掩码一起使用:
find . -type f -perm +111 -print
在此上下文中,“ +”表示“设置了这些位中的任何一个”,并且111是执行位。
请注意,这与-executable
GNU find中的谓词不同。特别是,-executable
测试文件可以由当前用户执行,而-perm +111
仅测试是否设置了任何执行权限。
GNU find的较早版本也支持该-perm +111
语法,但是从4.5.12开始,不再支持该语法。而是,您可以使用-perm /111
来获得此行为。
find: invalid mode ‘+111’
findutils 4.5.11 4.fc20 错误。
/
代替+
。有关更多详细信息,请参见更新后的答案。
-L
选项:find -L ...
。
-perm +111
可能会产生误报,即当前用户无法实际执行的文件。不能-executable
仅通过测试权限来进行仿真,因为所需的是将文件的用户和组标识与当前用户的关联。
提示@ gniourf_gniourf可以消除基本的误解。
该答案试图提供现有答案的概述,讨论它们的精妙之处和相对优点,并提供背景信息,特别是在便携性方面。
查找可执行文件可以涉及两个不同的用例:
请注意,在这两种情况下,都可以使用find -L ...
而不是仅仅find ...
为了找到可执行文件的符号链接。
请注意,最简单的以文件为中心的情况-寻找具有针对所有三个安全主体(用户,组,其他)的可执行权限位设置的可执行文件- 通常,但不一定会产生与以用户为中心的方案相同的结果-并且了解差异很重要。
-executable
)该接受的答案值得称赞的建议-executable
,IF GNU find
是可用的。
find
附带了大多数Linux发行版
-executable
仅匹配当前用户可以执行的文件(存在边际情况[1])。接受的答案()提供的BSD find
替代方案-perm +111
回答了一个不同的,以文件为中心的问题(正如答案本身所言)。
-perm
回答用户 -centric问题是不可能的,因为我们需要的是对有关该文件的用户和组身份给当前用户的,而-perm
只能测试文件的权限。find
功能,如果不使用外部实用程序就无法回答问题。因此,最好-perm
能(本身)做的是一个近似的-executable
。也许更接近的近似比-perm +111
是-perm -111
,以找到对所有安全主体(用户,组等)的可执行位的文件-这给我的印象中典型的真实世界的场景。另外,它也恰好符合POSIX的要求(用于find -L
包含符号链接,请参阅下文以获取更多解释):
find . -type f -perm -111 # or: find . -type f -perm -a=x
gniourf_gniourf的答案提供了一个真正的,可移植的,等同于-executable
使用的方法-exec test -x {} \;
,尽管是以性能为代价的。
-exec test -x {} \;
与结合使用-perm +111
(即,至少设置了一个可执行位的文件)可以帮助提高性能,而exec
不必为每个文件都调用(以下内容使用BSD find -perm +111
/ GNU find 的POSIX兼容等效物-perm /111
;有关详细说明,请参见下文) :
find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
-perm
)-perm
。
-perm
允许您测试任何文件权限,而不仅仅是可执行性。111
),而符号模式是字符串(例如a=x
)。u
(用户),g
(组)和o
(其他),或a
引用这三个主体。权限表示为x
可执行,例如,和使用运营商分配给主体=
,+
和-
; 有关包括八进制模式在内的完整讨论,请参见实用程序的POSIX规范chmod
。find
:
-
(例如-ug=x
)意味着:匹配具有所有指定权限的文件(但匹配文件可能具有附加权限)。755
)是指:具有此匹配的文件完整,准确的权限。+
/
[2]以文件为中心的命令示例
注意:
+
或/
。!
对于NOT(GNU查找和BSD查找也允许-not
);请注意,\!
在示例中使用该命令是为了防止!
shell历史记录扩展-a
用于AND(GNU查找和BSD查找也允许-and
)-o
用于OR(GNU查找和BSD查找也允许-or
)-
,=
and +
运算符可以互换使用(例如,-u=x
等效于-u+x
-除非-x
以后再应用,但这没有任何意义)。,
加入部分模式; 暗含AND逻辑;例如,-u=x,g=x
意味着必须同时设置用户和组可执行位。-perm
带有非主要符号的单独表达式!
。-print
,或-perm
;也被称为行动和测试在GNU发现)的隐含与加盟-a
(逻辑与),以及-o
和可能的括号(转义为\(
和\)
的壳),需要执行或逻辑。find -L ...
find ...
为了使符号链接也与可执行文件
匹配,使用了不只是-L
指示发现评估符号链接的目标,而不是符号链接本身;因此,如果没有-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] -executable
从man find
GNU find 4.4.2开始的描述:
匹配可执行文件和可搜索目录(在文件名解析的意义上)。这考虑了-perm测试忽略的访问控制列表和其他权限伪像。该测试利用了access(2)系统调用,因此可以被执行UID映射(或根压缩)的NFS服务器所欺骗,因为许多系统在客户端的内核中实现了access(2),因此无法利用服务器上保存的UID映射信息。因为此测试仅基于access(2)系统调用的结果,所以不能保证可以成功执行该测试成功的文件。
[2] 早于4.5.12的 GNU find版本也允许使用prefix +
,但首先不建议使用,最后将其删除,因为+
与符号模式结合使用可能会产生意外结果,因为它们被解释为确切的权限掩码。如果您(a)在版本上运行之前 4.5.12 和(二)限制自己八进制模式而已,你可以摆脱使用+
与这两个 GNU发现和BSD的发现,但它不是一个好主意。
为了使另一种可能性1查找当前用户可执行的文件:
find . -type f -exec test -x {} \; -print
(这里的测试命令很可能是在PATH中找到的命令/usr/bin/test
,而不是内置命令)。
1仅当-executable
标记find
不可用时才使用此功能!这与-perm +111
解决方案有细微的差别。
'{}'
或\{\}
。
-executable
或类似我的命令执行的命令。
find . -type f -perm -u=x
是不是相当于-executable
:-executable
匹配用户可以执行所有文件,其中包括g+x
如果我属于适当的组,则o+x
实际上-perm -u=x
会找到许多用户无法执行的文件,而错过了一些用户可以执行的文件。”
{}
是一种假设性的必要(并且引用也无害),但实际上在类似POSIX的shell和中没有必要csh
。你知道炮弹其中它是必需的?
fish
中 {}
必须确实以'{}'
或进行转义\{\}
。需要注意的是bash
,ksh
和zsh
提供同类括号扩展的; 然而,它们打印无引号标记{}
为是(并且因此:无需逸出),因为它们不认为这是一种有效的括号表达式(它们需要至少2代币,或有效的数字序列表达式),而fish
认为{}
一个有效撑导致空字符串的表达式。
您可以使用-executable
测试标志:
-executable
Matches files which are executable and directories which are
searchable (in a file name resolution sense).
-rw-r-xr-x
它-executable
不会检测
这对我有用,并想到了分享...
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
file
!
find ./ -mime application/x-sharedlib -o -mime application/x-dosexec
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 . -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}'<<< $ LINE)”“反映您在哪里寻找文件。查找输出字符串,您需要将“ NF”替换为正确的数字位置。如果分隔符不是空格,则还需要告诉awk分隔符是什么。
真是太荒谬了,这不是一件容易的事,更不用说几乎不可能了。举起手来,我遵从Apple / Spotlight ...
mdfind 'kMDItemContentType=public.unix-executable'
至少有效!
mdfind
高兴在OSX 上了解。注意,您的命令报告了整个系统的 Unix可执行文件。mdfind -onlyin . 'kMDItemContentType=public.unix-executable'
将结果限制为当前目录的子树。次要景点:不支持仅将搜索限制到特定目录(不包含子文件夹)。显然从未包含指向可执行文件的符号链接。奇怪的是,一旦mdfind
找到了可执行文件,随后就不会删除可执行文件。
mdfind -onlyin . 'kMDItemContentType=public.unix-executable'
行为与实际find . -type f -perm +111 -print
情况相同。也就是说,它查找具有任何可执行位的文件,这可能会产生误报(尽管在实践中可能不是问题)-要真正仅使用BSD find查找当前用户可执行的文件,请参见@gniourf_gniourf的答案。使用find
基于解决方案的优点是,您可以找到指向可执行文件的符号链接(如果需要)(选项-L
),这mdfind
似乎是做不到的。
zsh
提示-不知道;(看来你可以任意匹配的可执行文件(*
)或符号链接(@
),但不能同时,对吧?)。关于您的原始观点:让我重申find . -type f -perm +a=x
一下:mdfind
在提供更多灵活性的同时,将执行您的命令所执行的操作。您甚至可以将其重新构造为符合POSIX的格式。
答案很简单:“您的可执行文件位于PATH变量包含的目录中”,但这实际上找不到您的可执行文件,并且可能会丢失很多可执行文件。
我对Mac不太了解,但我认为“ mdfind'kMDItemContentType = public.unix-executable'”可能会遗漏解释脚本等内容
如果您可以找到设置了可执行位的文件(不管它们是否实际可执行),就可以了
find . -type f -perm +111 -print
支持的“ -executable”选项将进一步过滤acl和其他权限工件,但在技术上与“ -pemr +111”没有太大区别。
也许将来find会支持“ -magic”,并让您显式查找具有特定魔术ID的文件...但是您必须指定以优化所有可执行格式的魔术ID。
我不知道在UNIX上技术上正确的简便方法。
因此,如果您实际上只是想查找可执行文件的类型(例如脚本,ELF二进制文件等。等等),而不仅仅是具有执行权限的文件,那么您可能想做更多类似的事情(其中当前目录可以替换为任何内容)。您想要的目录):
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命令返回的任何其他信息。
此处确切的报价规则非常模糊,因此我最终还是通过反复试验得出结论,但我希望听到正确的解释。
我遇到了同样的问题,答案出在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)