常用命令
通过正则表达式,来匹配文件名:
find . -regextype posix-egrep \ -regex '\./[a-f0-9\-]{36}\.jpg' # 命令 find 匹配相对路径,所以以 ./ 开始
在当前目录下,找到行数大于 2 的文件:
find . -maxdepth 1 -type f \ -exec sh -c 'test $( wc -l {} | cut -f1 -d" " ) -gt "2"' \; -print
在特定名称的目录内,进行文件查找,并排除某些文件:
find . -maxdepth 1 -type f \ -exec sh -c 'test $( wc -l {} | cut -f1 -d" " ) -gt "2"' \; -print
或(or)操作:
find /media/d/ -type f -size +50M ! \( -name "*deb" -o -name "*vmdk" \)
删除目录:
find ~ -path '*/__pycache__/*' -delete # 先,清空在目录内的文件 find ~ -type d -name '__pycache__' -empty -delete # 再,删除当前目录;
语法格式
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]
命令描述
本手册页记录了 find 的 GNU 版本。GNU find 根据优先级规则(参见 OPERATORS 部分),从左到右依次评估给定的表达式,搜索以每个给定起始点为根的目录树,直到结果已知(and 操作左侧为 false,或者 or 操作左侧为 true),此时 find 会移动到下一个文件名。如果没有指定起始点,`.’ 假设;
如果在安全性很重要的环境中使用 find(例如,如果使用它来搜索其他用户可写的目录),应该阅读 findutils 文档的“Security Considerations”一章,该文章称为“Finding Files”并附带 findutils。该文档还包含比本手册页更多的细节和讨论,因此可能会发现它是一个更有用的信息来源;
命令结构简述
选项-H、-L、-P 控制符号链接的处理;
后面紧跟 starting-point 被认为是要检查的文件或目录的名称。如果没有给出路径,则使用当前目录;
当遇到第一个以“-”开头的参数,或者参数`(‘或`!’,即 expression 部分。该部分的任何参数被视为描述要搜索内容的表达式。如果没有给出表达式,则使用表达式-print(但是应该考虑使用-print0);
本手册页主要讨论 expression 列表中的“options”。这些选项控制 find 的行为,但在最后一个路径名后立即指定。五个“真实”选项-H,-L,-P,-D,-O 必须出现在第一个路径名之前(如果有的话)。双破折号(–)也可用于表示任何剩余参数不是选项(如果在 starting-point 列表中使用通配符,确保所有起始点以“./”或“/”开头,通常会更安全) ;
命令支持的选项及含义
[-H] [-L] [-P] [-D debugopts] [-Olevel]
-P
使用符号链接本身,而不是它指向的文件。这是默认行为。当 find 查看或打印文件信息,并且文件是符号链接时,所使用的信息应取自符号链接本身的属性;
-L
遵循符号链接。当查找或打印有关文件的信息时,所使用的信息应取自链接指向的文件的属性,而不是来自链接本身(除非它是一个已破损的符号链接,或 find 无法检查链接指向的文件)。此选项隐含了-noleaf。如果在-L 之后使用-P 选项,那么-noleaf 仍然有效。如果-L 生效且 find 在搜索期间发现指向子目录的符号链接,则将搜索符号链接指向的子目录;
-H
除处理命令行参数外,不使用符号链接所指向的文件,而是符号链接本身。当 find 查看或打印有关文件的信息时,所使用的信息应取自符号链接本身的属性。此行为的唯一例外是在命令行上指定的文件是符号链接,并且可以解析链接。对于这种情况,使用的信息取自链接指向的任何内容(即,遵循链接)。如果无法检查符号链接指向的文件,则有关链接本身的信息将用作后备。如果-H 生效并且命令行中指定的路径之一是指向目录的符号链接,则将检查该目录的内容(当然-maxdepth 0 会阻止此操作);
-D debugopts
打印诊断信息;这有助于诊断“为什么 find 没有预期执行”的问题。调试选项列表应以逗号分隔。在 findutils 的发行版之间,不保证调试选项的兼容性。有关有效调试选项的完整列表,请参阅 find -D help 的输出。有效的调试选项包括:
help,解释调试选项;
opt,打印与表达式树优化相关的诊断信息;请参阅-O 选项;
rates,打印一个摘要,指示每个谓词成功或失败的频率;
search,详细浏览目录树;
stat,打印使用 stat 和 lstat 系统调用检查的文件的消息。find 尝试最小化这种调用;
tree,以原始和优化的形式显示表达式树;
-Olevel
启用查询优化。find 重新排序测试以加快执行速度,同时保持整体效果;也就是说,具有副作用的谓词不会相对于彼此重新排序。在每个优化级别执行的优化如下:
基于成本的优化器可以确定任何给定测试成功的可能性。在某些情况下,概率考虑了测试的特定性质(例如,假定-type f 比-type c 更可能成功)。目前正在评估基于成本的优化工具。如果它实际上没有提高 find 的性能,它将再次被删除。相反,随着时间的推移,可以在较低的优化级别上实现被证明是可靠,稳健和有效的优化。但是,4.3.x 版本系列中的默认行为(即优化级别 1)不会更改。findutils 测试套件在每个优化级别上运行 find 的所有测试,并确保结果相同;
附加说明
当-L 选项生效时,谓词-type 将始终与符号链接指向的文件类型匹配,而不是链接本身(除非符号链接已破损)。在执行 find 时,可能导致符号链接断开的操作(例如-delete)可能会导致混淆行为。使用-L 会导致-lname 和-ilname 谓词始终返回 false;
如果指定了多个-H,-L,-P,则每个都覆盖其他的;出现在命令行上的最后一个生效。因此除非指定了-H 或-L,否则应认为-P 选项有效(因为它是默认值);
在任何搜索开始之前,GNU find 在处理命令行期间经常 stats 文件。这些选项也会影响这些参数的处理方式。具体来说,有许多测试将命令行中列出的文件与我们当前正在考虑的文件进行比较。在每种情况下,都将检查命令行中指定的文件,并保存其某些属性。如果指定文件实际上是符号链接,并且-P 选项有效(或者如果既未指定-H 也未指定-L),则用于比较的信息将从符号链接的属性中获取。否则,它将从链接指向的文件的属性中获取。如果 find 无法跟踪链接(例如,因为它没有足够的权限,或链接指向不存在的文件),将使用链接本身的属性;
当-H 或-L 选项生效时,任何列为-newer 参数的符号链接都将被解析,时间戳将从符号链接指向的文件中获取。同样适用于-newerXY,-anewer,-cnewer;
-follow 选项与-L 具有类似的效果,但它在它出现的位置生效(即,如果不使用-L 选项,但是使用-follow 选项,则在命令行上的-follow 之后出现的任何符号链接将是被解除引用,而之前的那些不会);
命令行中的 EXPRESSION 参数
参数 starting-point 列表后面的命令行部分是 expression。这是一种查询规范,描述了我们如何匹配文件以及我们如何处理匹配的文件。expression 由一系列事物组成:
如果整个表达式不包含-prune 或-print 之外的任何Actions,则对整个表达式为 True 的所有文件执行-print;
动作-delete 也像一个选项(因为它隐含了-depth);
POSITIONAL OPTIONS
位置选项始终返回 True。它们仅影响后面在命令行上发生的测试:
-daystart
测量时间(-amin,-atime,-cmin,-ctime,-mmin 和-mtime)时,从今天开始时刻进行计算,而不是从 24 小时前。此选项仅影响稍后在命令行中显示的测试;
-follow
不推荐使用;请改用-L 选项。引用符号链接指向的文件。隐含着-noleaf 选项。选项-follow 仅影响命令行上在它之后的那些测试。除非指定了-H 或-L 选项,否则-follow 选项的位置会更改-newer 谓词的行为;如果它们是符号链接,那么列为-newer 参数的任何文件都将引用真实文件。这同样适用于-newerXY,-anewer,-cnewer。类似地,-type 谓词将始终与符号链接指向的文件类型匹配,而不是链接本身。使用-follow 会导致-lname 和-ilname 谓词始终返回 False;
-regextype type
更改-regex 和-iregex 测试所理解的正则表达式语法,这些语法稍后在命令行中发生。要查看已知的正则表达式类型,请使用-regextype help。Texinfo 文档(参见另请参阅)解释了各种类型的正则表达式的含义和差异;
-warn, -nowarn
打开或关闭警告信息。这些警告是关于命令行用法的,而不适用于在搜索目录时可能遇到的任何条件。如果标准输入是 tty,则默认行为对应于-warn,否则对应于-nowarn。如果生成与命令行使用相关的警告消息,则不会影响 find 的退出状态。如果设置了 POSIXLY_CORRECT 环境变量,并且还使用了-warn,则不会指定哪个(如果有)警告将处于活动状态;
GLOBAL OPTIONS
全局选项总是返回 True。即使之前在命令行上发生的测试,全局选项也会生效。为防止混淆,应在 starting-point…之后的命令行中指定全局选项,就在第一个测试、位置选项、操作之前。如果在其他位置指定了全局选项,则 find 将发出警告消息,说明这可能会造成混淆;
全局选项出现在 starting-point…之后,因此与-L 的选项是不同类型的;
-d
-depth 的同义词,用于与 FreeBSD,NetBSD,MacOS X,OpenBSD 的兼容性;
-depth
在目录本身之前处理每个目录的内容。动作-delete 也隐含-depth;
-ignore_readdir_race
通常,find 会在无法 stat 文件时发出错误消息。如果提供此选项,并且在 find 从目录中读取文件名称和尝试统计文件的时间之间删除文件,则不会发出错误消息。这也适用于在命令行上给出其名称的文件或目录。此选项在读取命令行时生效,这意味着无法使用此选项搜索文件系统的一部分,并且再关闭此选项搜索另一部分(如果需要这样做,则需要使用两个 find 命令,一个带有该选项,一个不带该选项);
-noignore_readdir_race
关闭-ignore_readdir_race 的效果;
-maxdepth levels
在 starting-point 下,最多下降 level(非负整数)级目录。-maxdepth 0表示仅将测试和操作应用于 starting-point 本身;
-mindepth levels
不要在低于 level(非负整数)的级别应用任何测试或操作。-mindepth 1表示处理除 starting-point 之外的所有文件;
-mount
不要查找其他文件系统上的目录。是-xdev的替代,用于与其他某些版本的 find 兼容;
-xdev
不要查找其他文件系统上的目录;
-noleaf
不要通过假设目录包含比硬链接数少 2 个子目录来进行优化。当搜索不遵循 Unix 目录链接约定的文件系统时,需要此选项,例如 CD-ROM 或 MS-DOS 文件系统或 AFS 卷装入点;
普通 Unix 文件系统上的每个目录至少有 2 个硬链接:它的名称和它的`.’ 条目。此外,它的子目录(如果有的话)每个都有一个链接到该目录的“..”条目。当 find 正在检查一个目录时,在它确定了比目录的链接数少 2 个子目录之后,它知道目录中的其余条目是非目录(目录树中的`leaf’文件)。如果只需要检查文件的名称,则无需对它们进行 stat;这使搜索速度显着提高;
-version, –version
打印 find 版本号并退出;
-help, –help
打印查找和退出命令行用法的摘要;
TESTS
某些测试(例如-newXY 和-samefile)允许比较当前正在检查的文件和命令行上指定的某个参考文件。使用这些测试时,参考文件的解释由选项-H,-L,-P 以及任何先前的-follow 确定,但参考文件仅在解析命令行时检查一次。如果无法检查引用文件(例如,stat(2)系统调用失败),则会发出错误消息,然后 find 以非零状态的退出;
数字参数有三种形式:“+n”大于 n;“-n”小于 n;“n”等于 n;
-amin n
文件最后一次访问是在 n 分钟前;
-anewer file
最近一次访问文件的时间比文件 file 修改时间更新。如果 file 是符号链接,且-H 选项或-L 选项生效,则始终使用它指向的文件的访问时间;
-atime n
文件最后一次访问在 n*24 小时前。当 find 指出上次访问文件 24 小时前的数字时,忽略任何小数部分,因此为了匹配-atime +1,必须至少在两天前访问该文件;
-cmin n
文件的状态最后一次更改在 n 分钟前;
-cnewer file
最近更改了文件的状态,而更改时间比文件 file 修改时间更新。如果 file 是符号链接,且-H 选项或-L 选项生效,则始终使用它指向的文件的状态更改时间;
-ctime n
文件状态最后一次更改为 n*24 小时前。请参阅-atime 的注释,以了解舍入如何影响文件状态更改时间的解释;
-mmin n
文件的数据是在 n 分钟前修改的;
-mtime n
文件的数据上次修改时间为 n*24 小时前。请参阅-atime 的注释,以了解舍入如何影响文件修改时间的解释;
-newer file
文件的修改时间比文件 file 的时间更新。如果 file 是符号链接且-H 选项或-L 选项生效,则始终使用它指向的文件的修改时间;
-newerXY reference
如果正在处理的文件的时间戳 X 比文件 reference 的时间戳 Y 更新,则返回成功。字母 X 和 Y 可以是以下任何字母:
B,文件 reference 的生成时间
c,文件 reference 的 inode 状态更改时间
m,文件 reference 的修改时间
t,将 reference 直接解释为时间
有些组合无效;例如,X 为 t 则无效。某些组合未在所有系统上实施; 例如,并非所有系统都支持 B。如果指定了无效或不受支持的 XY 组合,则会导致致命错误 时间规范被解释为 GNU date 的-d 选项的参数。如果尝试使用参考文件的创建时间,并且无法确定创建时间,则会产生致命错误消息。如果指定的测试涉及正在检查的文件的创建时间,则对于创建时间未知的任何文件,此测试将失败;
-empty
文件为空,是常规文件或目录;
-false
总是返回 False;
-true
总是为 True;
-fstype type
文件位于类型 type 的文件系统上。有效的文件系统类型因 Unix 的不同版本而异;在某些版本的 Unix 或其他版本上接受的文件系统类型的不完整列表是:ufs,4.2,4.3,nfs,tmp,mfs,S51K,S52K。可以使用-printf 和%F 指令来查看文件系统的类型;
-gid n
文件的数字 GID 为 n;
-group gname
文件所属的组名为 gname(允许数字类型的组 ID);
-nogroup
没有组对应于文件的数字 GID;
-uid n
文件的数字 UID 为 n;
-user uname
文件由用户 uname 拥有(允许使用数字用户 ID);
-nouser
没有用户对应于文件的数字 UID;
-name pattern
文件名的基础(删除了前导目录的路径)与 Shell 模式模式匹配。因为删除了前导目录,所以考虑与-name 匹配的文件名永远不会包含斜杠,所以-name a/b永远不会匹配任何东西(可能需要使用-path)。如果尝试执行此操作,则会发出警告,除非设置了环境变量 POSIXLY_CORRECT。元字符(`*’,`?’,`[]’)匹配在基本名称的开头的`.’ (这是 findutils-4.2.2 的变化;请参阅下面的「标准一致性」部分)。要忽略目录及其下的文件,请使用-prune;请参阅-path 描述中的示例。大括号不被认为是特殊的,尽管有些 Shell(包括 Bash)在 Shell 模式中具有支持特殊含义的大括号。使用 fnmatch(3)库函数执行文件名匹配。不要忘记将模式用引号括起来,以防止它被 Shell 扩展;
-lname pattern
文件是一个符号链接,其内容与 Shell 模式 pattern 匹配。元字符不特殊处理“/”或“.” 。如果-L 选项或-follow 选项生效,则除非符号链接断开,否则此测试将返回 false;
-ilname pattern
与-lname 类似,但匹配不区分大小写。如果-L 选项或-follow 选项生效,则除非符号链接断开,否则此测试将返回 False;
-iname pattern
与-name 类似,但匹配不区分大小写。例如,模式“fo*”和“F??” 匹配文件名`Foo’,`FOO’,`foo’,`fOo’等。模式`*foo*`也匹配一个名为’.foobar’的文件;
-inum n
文件的索引节点号为 n。通常更容易使用-samefile 测试;
-path pattern
文件名与 Shell 模式 pattern 匹配。元字符不特殊处理“/”或“.”特别;所以find . -path "./sr*sc"将打印一个名为`./src/misc’的目录(如果存在);
要忽略整个目录树,请使用-prune 而不是检查树中的每个文件。例如,要跳过目录`src/emacs’及其下的所有文件和目录,并打印找到的其他文件的名称,执行:find . -path ./src/emacs -prune -o -print
请注意,模式匹配测试适用于整个文件名,从命令行中指定的 starting-point 之一开始。如果相关 starting-point 也是绝对路径,那么在此处使用绝对路径名称才有意义。这意味着命令find bar -path /foo/bar/myfile -print永远不会匹配任何内容;
find 将“-path 参数与目录名的串联”和它“正在检查的文件的基本名称”进行比较。由于连接将永远不会以斜杠结束,因此以斜杠结尾的-path 参数将不匹配任何内容(除了可能是命令行上指定的起始点)。HP-UX find 也支持谓词路径,它是 POSIX 2008 标准的一部分;
-ipath pattern
类似于-path。但是匹配不区分大小写;
-wholename pattern
请参阅-path。这种替代方案的可移植性弱于比-path;
-iwholename pattern
见-ipath。这种替代方案的可移植性不如-ipath;
-regex pattern
文件名与正则表达式 pattern 匹配。这是整个路径上的匹配,而不是搜索。例如,要匹配名为`./fubar3’的文件,可以使用正则表达式`.*bar.’,`.*b.*3’,但不是`f.*r3’。find 所理解的正则表达式默认为 Emacs Regular Expressions,但可以使用-regextype 选项进行更改;
-iregex pattern
类似与-regex 选项,但是匹配忽略大小写;
-links n
文件具有 n 个链接;
-samefile name
文件指向的是与 name 相同的 inode。当-L 生效时,这可以包括符号链接;
-perm mode
文件的权限位是精确模式(八进制或符号)。由于需要完全匹配,如果要将此形式用于符号模式,则可能必须指定相当复杂的模式字符串。例如,`-perm g=w’将仅匹配具有模式 0020 的文件(即,组写权限是唯一的权限集);
更有可能想要使用`/’或`-‘形式,例如`-perm -g=w’,它匹配任何具有组写权限的文件。有关一些说明性示例,请参见“示例”部分;
-perm -mode
为文件设置了所有权限位 mode。此模式中接受符号模式,这通常是希望使用它们的方式。如果使用符号模式,则必须指定“u”,“g”或“o”。有关一些说明性示例,请参见“示例”部分;
-perm /mode
为文件设置了任何权限位 mode。这种形式接受符号模式。如果使用符号模式,则必须指定“u”,“g”或“o”。有关一些说明性示例,请参见“示例”部分。如果 mode 中未设置权限位,则此测试将匹配任何文件(此处的想法与-perm -000 的行为一致);
-perm +mode
不再支持此功能(自 2005 年以来已弃用)。请改用-perm /mode;
-size n[cwbkMG]
文件使用 n 个单位的空间,向上舍入。可以使用以下后缀:
c,表示字节
w,表示双字节字
k,表示千字节(1024 字节单位)
M,表示兆字节(单位为 1048576 字节)
G,千兆字节(单位为 1073741824 字节)
大小不计算间接块,但它会计算实际未分配的稀疏文件中的块 请记住,-printf 的`%k’和`%b’格式说明符处理稀疏文件的方式不同。`b’后缀总是表示 512 字节块,而不是 1 千字节块,这与-ls 的行为不同;
与往常一样,+和-前缀表示大于和小于。请记住,大小会向上舍入到下一个单位。因此,-size -1M不等于-size -1048576c。前者只匹配空文件,后者匹配 1 到 1,048,575 字节的文件;
-type c
文件类型为 c:
c,字符(无缓冲)特殊文件
d,目录
p,命名管道(FIFO)
f,常规文件
l,符号链接;如果-L 选项或-follow 选项生效,则永远不会为 True,除非符号链接损坏。如果要在-L 生效时搜索符号链接,请使用-xtype;
s,套接字
D,door(Solaris)
要一次搜索多个类型,可以提供由逗号“,”(GNU 扩展名)分隔的类型字母的组合列表;
-xtype c
除非文件是符号链接,否则与-type 相同。对于符号链接:如果指定了-H 或-P 选项,则如果文件是指向类型 c 的文件的链接,则为 True;否则为 False。如果给出了-L 选项,则如果 c 为“l”则为 True。换句话说,对于符号链接,-xtype 检查-type 不检查的文件的类型;
-used n
文件是在上次更改状态后的第 n 天访问的;
-writable
匹配可写的文件。这会考虑 ACL 和-perm 测试忽略的其他权限假象。此测试使用 access(2)系统调用,因此可以被执行 UID 映射(或 root-squashing)的 NFS 服务器所欺骗,因为许多系统在客户端内核中实现 access(2),因此无法使用 服务器上保存的 UID 映射信息;
-readable
匹配可读的文件。这会考虑 ACL 和-perm 测试忽略的其他权限假象。此测试使用 access(2)系统调用,因此可以被执行 UID 映射(或 root-squashing)的 NFS 服务器所欺骗,因为许多系统在客户端内核中实现 access(2),因此无法使用 服务器上保存的 UID 映射信息;
-executable
匹配可执行文件和可搜索的目录(在文件名解析意义上)。这会考虑访问控制列表和-perm 测试忽略的其他权限假象。此测试使用 access(2)系统调用,因此可以被执行 UID 映射(或 root-squashing)的 NFS 服务器所欺骗,因为许多系统在客户端内核中实现 access(2),因此无法使用 服务器上保存的 UID 映射信息。由于此测试仅基于 access(2)系统调用的结果,因此无法保证可以实际执行此测试成功的文件;
-context pattern
(仅限 SELinux)文件的安全上下文与 glob 模式匹配;
ACTIONS
-delete
删除文件;如果删除成功,则为 true。如果删除失败,则会发出错误消息。如果-delete 失败,则 find 的退出状态将为非零(最终退出时)。使用-delete 会自动打开`-depth’选项;
警告:不要忘记将 find 命令行计算为表达式,因此首先使用-delete 会使 find 尝试删除指定起始点以下的所有内容。在测试稍后打算与-delete 一起使用的 find 命令行时,应该明确指定-depth 以避免以后出现意外。因为-delete 隐含了-depth,所以不能有效地一起使用-prune 和-delete;
-exec command ;
执行命令;如果返回 0 状态,则返回 true。find 的所有后续参数都被视为命令的参数,直到遇到由`;’组成的参数为止。在命令参数中任何位置出现的字符串`{}’都会替换为当前被处理的文件名,而不仅仅是在某些版本的 find 中的参数中。这两种结构都可能需要进行转义(使用“\”)或引用,以防止它们被 Shell 扩展。有关使用-exec 选项的示例,请参阅“示例”部分。为每个匹配的文件运行一次指定的 command。该 command 在起始目录中执行。围绕使用-exec 操作存在不可避免的安全问题;应该使用-execdir 选项;
-exec command {} +
操作-exec 的此变体,在所选文件上运行指定的命令,但是通过在命令行末尾最佳每个选定的文件名来构建命令;命令的调用总数将远远少于匹配文件的数量。命令行的构建方式与 xargs 构建命令行的方式大致相同。在命令中只允许一个“{}”实例,并且(当从 Shell 调用 find 时)应该引用它(例如,“{}”),以保护它不被 Shell 解释。该命令在起始目录中执行。如果任何调用返回非零值作为退出状态,则 find 返回非零退出状态。如果 find 遇到错误,这有时会导致立即退出,因此可能根本不会运行某些挂起的命令;
-exec 的这个变体总是返回 true;
-execdir command ;
-execdir command {} +
与-exec 类似,但指定的命令是从包含匹配文件的子目录运行的,而不是开始查找的目录。与-exec 一样,如果从 Shell 调用 find,则应引用{}。这是一种更安全的调用命令的方法,因为它可以在解析匹配文件的路径时避免竞争条件。与-exec 操作一样,-execdir 的`+’形式将构建一个命令行来处理多个匹配的文件,但任何给定的命令调用都只会列出存在于同一子目录中的文件。如果使用此选项,则必须确保$PATH 环境变量不引用`.’;否则,攻击者可以通过在将运行-execdir 的目录中保留适当命名的文件来运行他们喜欢的任何命令。这同样适用于$PATH 中的条目为空或者不是绝对目录名称。如果任何 command 调用返回非零值作为退出状态,则 find 返回非零退出状态。如果 find 遇到错误,这有时会导致立即退出,因此可能根本不会运行某些挂起的命令。操作的结果取决于正在使用变体“+”或“;”;-execdir command {} +总是返回 true,而-execdir command {} ;仅当命令返回 0 时,才返回 true;
-ok command ;
像-exec 一样,但首先询问用户。如果用户同意,请运行该命令。否则只返回 false。如果运行该命令,则从 /dev/null 重定向其标准输入;
对提示的响应与一对正则表达式匹配,以确定它是肯定的还是否定的。如果设置了“POSIXLY_CORRECT”环境变量,则从系统获取此正则表达式,或者从 find 的消息转换中获取此正则表达式。如果系统没有合适的定义,将使用 find 自己的定义。在任何一种情况下,正则表达式本身的解释都将受到环境变量’LC_CTYPE’(字符类)和’LC_COLLATE’(字符范围和等价类)的影响;
-okdir command ;
像-execdir 一样,但首先以与-ok 相同的方式询问用户。如果用户不同意,则返回 false。如果运行该命令,则从 /dev/null 重定向其标准输入;
-ls
True;在标准输出上以ls -dils格式列出当前文件。除非设置了环境变量 POSIXLY_CORRECT,否则块计数为 1K 块,在这种情况下使用 512 字节块。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-fls file
True;像-ls 一样,但是写入文件像-fprint。始终创建输出文件,即使谓词不匹配也是如此。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-fprint file
True;将完整文件名打印到文件 file 中。如果运行 find 时文件不存在,则创建该文件;如果确实存在,则会被截断。文件名`/dev/stdout’和`/dev/stderr’是专门处理的;它们分别指标准输出和标准错误输出。始终创建输出文件,即使谓词从不匹配也是如此。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-fprint0 file
True;像-print0,但写入文件像-fprint。始终创建输出文件,即使谓词从不匹配也是如此。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-fprintf file format
True;像-printf,但写入文件像-fprint。始终创建输出文件,即使谓词从不匹配也是如此。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-print
True;在标准输出上打印完整文件名,然后是换行符。如果将 find 的输出传递给另一个程序,并且搜索的文件可能包含换行符,那么应该认真考虑使用-print0 选项而不是-print。有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-print0
True;在标准输出上打印完整文件名,后跟空字符(NUL,而不是-print 使用的换行符)。这允许处理 find 输出的程序正确解释包含换行符或其他类型的空格的文件名。此选项对应于 xargs 的-0 选项;
-printf format
True;标准输出上的打印格式 format,解释`\’转义和’%’指令。可以使用像 C 函数`printf’一样指定字段宽度和精度。请注意,许多字段打印为%s 而不是%d,这可能意味着标记不能像期望的那样工作。这也意味着`-‘标志确实有效(它强制字段左对齐)。与-print 不同,-printf 不会在字符串末尾添加换行符。转义和指令如下:
\b,退格;
\c,立即停止从此格式打印,并刷新输出;
\f,换页(FF);
\n,换行;
\r,回车;
\t,水平制表符;
\v,垂直制表符;
\0,ASCII NUL;
\\,一个字面反斜杠(\);
\NNN, ASCII 码为 NNN(八进制)的字符;
\CHAR,CHAR 为任何其他字符,这将被视为普通字符,因此它们都被打印出来;
%%,一个百分号(%);
%a,文件的最后访问时间,采用 C 的`ctime’函数返回的格式;
%Ak,文件的最后访问时间。采用 k 指定的格式,即“@”或 C 中`strftime’函数的指令。k 的可能值如下,由于系统之间的“strftime”不同,其中一些指令可能并非在所有系统上都可用:
H,小时 (00..23)
I,小时 (01..12)
k,小时 ( 0..23)
l,小时 ( 1..12)
M,分钟 (00..59)
p,本地的 AM 或 PM
r,12 小时制的时间 (hh:mm:ss [AP]M)
S,秒 (00.00 .. 61.00). 包含小数部分;
T,24 小时制的时间 (hh:mm:ss.xxxxxxxxxx)
+,日期和时间,由减号(+)分隔。例如:`2004-04-28+22:22:05.0’。这是 GNU 扩展。显示当前时区的时间(受 TZ 环境变量的影响)。秒中包含小数部分;
X,本地时间的表示(H:M:S)。秒字段包括小数部分;
Z,时区(例如,EDT),或者如果没有确定时区可,则为空;
a,本地语言环境中周的缩写 (Sun..Sat)
A,本地语言环境中完整的周名,变长 (Sunday..Saturday)
b,本地语言环境中缩写的月份名 (Jan..Dec)
B,本地语言环境中完整的月份名,变长 (January..December)
c,本地语言环境中日期时间 (Sat Nov 04 12:02:33 EST 1989)。格式与 ctime(3)相同,因此,为了保持与该格式的兼容性,秒字段中没有小数部分;
d,月份中的第几天 (01..31)
D,日期 (mm/dd/yy)
h,与 b 相同
j,day of year (001..366)
m,月份 (01..12)
U,一年中的第几周,周末是一周的第一天 (00..53)
w,一周中的第几天 (0..6)
W,一年中的第几周,周一是一周中的第一天 (00..53)
x,本地语言环境中日期表示 (mm/dd/yy)
y,年份的最后两位 (00..99)
Y,年份 (1970…)
%c,文件的最后状态更改时间,采用 C 的`ctime’函数返回的格式;
%Ck,文件的最后状态更改时间,以 k 指定的格式,与%A 相同;
%d,文件在目录树中的深度;0 表示文件是起始点;
%D,文件所在的设备编号(struct stat 的 st_dev 字段),以十进制表示;
%F,文件所在的文件系统的类型;此值可用于-fstype;
%g,文件的组名称或数字 GID(如果该组没有名称);
%G,文件的数字 GID;
%h,文件名的前导目录(除最后一个元素外其他的元素)。如果文件名不包含斜杠(因为它在当前目录中),%h 说明符将解释为“.”;
%p,文件名;
%P,文件名,但文件名中的起始点被移除;
%f,文件名,但是删除了任何前导目录的文件名(仅限最后一个元素);
%H,找到文件的起始点;
%i,文件的 inode 编号(十进制);
%k,在 1K 块中,用于此文件的磁盘空间量。由于磁盘空间是以文件系统块大小的倍数分配的,因此通常大于%s/1024,但如果文件是稀疏文件,它也可以更小;
%l,符号链接的对象(如果文件不是符号链接,则为空字符串);
%m,文件的权限位(八进制)。此选项使用大多数 Unix 实现使用的“传统”数字模式,但如果的特定实现中使用八进制权限位的异常排序,将看到文件模式的实际值与%m 的输出之间的差异。如果想要在数字上使用一个前导零,应该使用#flag(例如,`%#m’);
%M,文件的权限(符号形式,如 ls)。findutils 4.2.5 及更高版本支持该指令;
%n,文件的硬链接数;
%s,文件的大小(以 BYTE 为单位);
%S,文件的稀疏性。计算公式为(BLOCKSIZE * st_blocks / st_size)。对于定长的普通文件,获得的确切值取决于系统。但是,正常稀疏文件的值小于 1.0,使用间接块的文件的值可能大于 1.0。用于 BLOCKSIZE 的值取决于系统,但通常为 512 字节。如果文件大小为零,则打印的值未定义。在缺乏对 st_blocks 支持的系统上,假定文件的稀疏性为 1.0;
%t,文件的最后修改时间,采用 C 中`ctime’函数返回的格式;
%Tk,文件的最后修改时间,以 k 指定的格式,与%A 相同;
%u,文件的用户名或数字用户 ID(如果用户没有名称);
%U,文件的数字 UID;
%y,文件的类型(如在 ls -l 中),U 表示未知类型(不应该发生)
%Y,文件类型(如同%y),加上符号符号:L 表示循环,N 表示不存在
%Z,(仅限 SELinux)文件的安全上下文;
%{ %[ %(,保留供将来使用;
对于任何其他字符后跟的’%’的形式,‘%’会被直接丢弃,但打印另一个字符(不依赖于此,因为以后可能会引入更多格式字符)。参数 format 末尾的“%”会导致未定义的行为,因为没有后续字符。在某些区域设置中,它可能会隐藏的门钥匙,而在其他地方,它可能会从正在阅读的内容中删除最后一页;
指令%m 和%d 支持#、0、+标志,但其他指令不支持,即使它们打印数字。不支持这些标志的数字指令包括 G,U,b,D,k,n。支持“-”格式标志,并将字段的对齐方式从右对齐(默认)更改为左对齐;
有关如何处理文件名中的异常字符的信息,请参见“异常文件”部分;
-prune
True;如果文件是目录,请不要进入该目录。如果给出-depth,则为 false;没有效果。因为-delete 暗示-depth,所以不能有效地一起使用-prune 和-delete;
-quit
立即退出。不会继续运行子进程,但不会处理命令行上指定的更多路径。例如,find /tmp/foo /tmp/bar -print -quit将仅打印 /tmp/foo。在 find 退出之前,将调用使用-execdir ... {} +构建的所有命令行。退出状态可能为零,也可能不为零,具体取决于是否已发生错误;
OPERATORS
按优先级递减的顺序列出可用的运算符:
( expr )
强制优先。由于括号对 Shell 是特殊的,因此通常需要引用它们。本手册页中的许多示例都使用反斜杠:\(... \),而不是(...);
! expr
如果 expr 为 False,则为 True。这个字符通常还需要保护,免受 Shell 解释;
-not expr
与! expr 相同,但不符合 POSIX;
expr1 expr2
连续两个表达式通过隐含的-a 连接;如果 expr1 为 false,则不计算 expr2;
expr1 -a expr2
与 expr1 expr2 相同;
expr1 -and expr2
与 expr1 expr2 相同,但不符合 POSIX;
expr1 -o expr2
或,如果 expr1 为真,则不评估 expr2;
expr1 -or expr2
与 expr1 -o expr2 相同,但不符合 POSIX;
expr1 , expr2
列表;始终评估 expr1 和 expr2。expr1 的值被丢弃;列表的值是 expr2 的值。逗号运算符可用于搜索几种不同类型的事物,但只能遍历文件系统层次结构一次。-fprintf 操作可用于将各种匹配的项列表到几个不同的输出文件中;
请注意-a 隐式指定时(例如,两个测试之间没有显式运算符)或显式的优先级高于-o。这意味着find . -name afile -o -name bfile -print永远不会打印 afile,因为-name bfile -print等同于-name bfile -a -print,因此-print仅仅作用于-name bfile;
特殊文件名
许多 find 的操作导致打印的数据在其他用户控制下。这包括文件名,大小,修改时间等。文件名是一个潜在的问题,因为它们可以包含除“\0”和“/”之外的任何字符。文件名中的异常字符可能会对终端造成意外,且通常不受欢迎的事情(例如,更改某些终端上功能键的设置)。如下所述,各种动作对异常字符的处理方式不同;
-print0, -fprint0
即使输出到达终端,也始终打印确切的文件名,不变;
-ls, -fls
不寻常的字符总是被转义。空格、反斜杠、双引号字符使用 C 风格转义打印(例如`\f’,`\”‘)。其他不常见的字符使用八进制转义打印。其他可打印字符(对于-ls 和-fls,这些是八进制 041 和 0176 之间的字符)按原样打印;
-printf, -fprintf
如果输出没有到达终端,则按原样打印。否则,结果取决于正在使用的指令。指令%D,%F,%g,%G,%H,%Y,%y 解释为不受文件所有者控制的值,因此按原样打印。指令%a,%b,%c,%d,%i,%k,%m,%M,%n,%s,%t,%u,%U 具有受文件所有者控制的值 ,但不能用于向终端发送任意数据,因此这些是按原样打印的。指令%f,%h,%l,%p,%P 会被引用,该引用以与 GNU ls 相同的方式执行,这与用于-ls 和-fls 的引用机制不同。如果能够决定使用什么格式来控制输出,那么通常最好使用`\0’作为终止符而不是使用换行符,因为文件名可以包含空格和换行符。`LC_CTYPE’环境变量的设置用于确定哪些字符需要引用;
-print, -fprint
引用的处理方式与-printf 和-fprintf 相同。如果在脚本中使用 find,或者匹配文件可能具有任意名称,则应考虑使用-print0 而不是-print;
操作-ok 和-okdir 按原样打印当前文件名。这可能会在将来的版本中发生变化;
标准一致性
为了最接近 POSIX 标准,应该设置 POSIXLY_CORRECT 环境变量。POSIX 标准(IEEE Std 1003.1,2003 Edition)中指定了以下选项:
-H,支持此选项;
-L,支持此选项;
-name,支持此选项,但 POSIX 一致性取决于系统的 fnmatch(3)库函数的 POSIX 一致性。从 findutils-4.2.2 开始,shell 元字符(例如`*’,`?’或`[]’)将匹配前导’.’,因为 IEEE PASC interpretation 126 要求这个。这是对先前版本的 findutils 的更改;
-type,支持。POSIX 指定“b”,“c”,“d”,“l”,“p”,“f”,“s”。GNU find 还支持表示 door 的“D”,OS 提供这些。此外,GNU find 允许在逗号分隔列表中一次指定多个类型;
-ok,支持。响应的解释是根据通过设置`LC_MESSAGES’环境变量选择的“yes”和“no”模式。当设置`POSIXLY_CORRECT’环境变量时,这些模式被系统定义为肯定(yes)或否定(no)响应。请参阅 nl_langinfo(3)的系统文档,特别是 YESEXPR 和 NOEXPR。如果未设置“POSIXLY_CORRECT”,则会从 find 自己的消息目录中获取模式;
-newer,支持。如果指定的文件是符号链接,则始终解析它。这是对以前行为的改变,以前从符号链接中获取相关时间;请参阅下面的历史部分;
-perm,支持。如果未设置 POSIXLY_CORRECT 环境变量,则支持在 POSIX 中无效的某些模式参数(例如+a+x),以实现向后兼容性;
其他谓词全部支持:-atime, -ctime, -depth, -group, -links, -mtime, -nogroup, -nouser, -print, -prune, -size, -user, -xdev
POSIX 标准指定括号((、)),否定(!),和(and),或(or、-a、-o)运算符;
所有其他选项,谓词,表达式等都是 POSIX 标准之外的扩展。但是,其中许多扩展并不是 GNU find 所特有的;
POSIX 标准要求 find 检测循环:
GNU find 符合这些要求。目录中包含硬链接到祖先目录的条目,则该目录链接数通常会低于它们应该的值。这可能意味着 GNU find 有时会优化远离子目录的访问,该子目录实际上是到祖先的链接。由于 find 实际上没有进入这样的子目录,因此允许它避免发出诊断消息。虽然这种行为可能有点令人困惑,但实际上任何人都不太可能依赖于这种行为。如果已使用-noleaf 关闭叶优化,则将始终检查目录条目,并在适当的位置发出诊断消息。符号链接不能用于创建文件系统循环,但如果正在使用-L 选项或-follow 选项,则当 find 遇到符号链接循环时会发出诊断消息。与包含硬链接的循环一样,叶优化通常意味着 find 知道它不需要在符号链接上调用 stat()或 chdir(),因此通常不需要此诊断;
支持-d 选项以兼容各种 BSD 系统,但应该使用 POSIX 兼容选项-depth;
POSIXLY_CORRECT 环境变量不会影响-regex 或-iregex 测试的行为,因为这些测试未在 POSIX 标准中指定;
注意事项
POSIX 标准为 find 指定的行为中存在固有的安全问题,因此无法修复。例如,-exec 操作本质上是不安全的,应该使用-execdir。有关更多信息,请参阅查找文件;
环境变量 LC_COLLATE 对-ok 操作没有影响;
历史
从 findutils-4.2.2 开始,在文件名模式中使用的 shell 元字符(例如`*’,`?’或`[]’)将匹配前导’.’,因为 IEEE PASC interpretation 126 要求这个;
从 findutils-4.3.3 开始,-perm /000 现在匹配所有文件,而不是 none;
在 findutils-4.3.3 中实现了纳秒分辨率的时间戳;
从 findutils-4.3.11 开始,-delete 动作将 find 的退出状态设置为失败时的非零值。但是,find 不会立即退出。以前,查找的退出状态不受-delete 失败的影响;
Feature Added in Also occurs in -newerXY 4.3.3 BSD -D 4.3.1 -O 4.3.1 -readable 4.3.0 -writable 4.3.0 -executable 4.3.0 -regextype 4.2.24 -exec ... + 4.2.12 POSIX -execdir 4.2.12 BSD -okdir 4.2.12 -samefile 4.2.11 -H 4.2.5 POSIX -L 4.2.5 POSIX -P 4.2.5 BSD -delete 4.2.3 -quit 4.2.3 -d 4.2.3 BSD -wholename 4.2.0 -iwholename 4.2.0 -ignore_readdir_race 4.2.0 -fls 4.0 -ilname 3.8 -iname 3.8 -ipath 3.8 -iregex 3.8
在 findutils-4.5.12 中删除了语法-perm +MODE,使用-perm /MODE。自从 2005 年发布的 findutils-4.2.21 以来,+MODE 语法已被弃用;
非 BUG 现象
Operator precedence surprises
命令查找find . -name afile -o -name bfile -print永远不会打印 afile,因为这实际上等同于find . -name afile -o \( -name bfile -a -print \)。请记住,-a 的优先级高于-o 的优先级,并且当测试之间没有指定运算符时,假定为-a;
“paths must precede expression” error message
$ find . -name *.c -print
find: paths must precede expression
Usage: find [-H] [-L] [-P] [-Olevel] [-D … [path…] [expression]
这是因为*.c 已被 shell 扩展,导致 find 实际上接收到如下命令行:find . -name frcode.c locate.c word_io.c -print。那个命令当然不会起作用。应该将模式括在引号中或转义通配符,而不是以这种方式执行操作:find . -name ‘*.c’ -print或者find . -name \*.c -print;
相关环境变量
LANG
为未设置或为 null 的国际化变量提供一个默认值;
LC_ALL
如果设置为非空字符串值,则覆盖所有其他国际化变量的值;
LC_COLLATE
POSIX 标准指定此变量影响用于-name 选项的模式匹配。GNU find 使用 fnmatch(3)库函数,因此对“LC_COLLATE”的支持取决于系统库。此变量也会影响对-ok 的响应的解释;而`LC_MESSAGES’变量选择用于解释对-ok 的响应的实际模式,模式中任何括号表达式的解释都将受到`LC_COLLATE’的影响;
LC_CTYPE
如果系统的 fnmatch(3)库函数支持此变量,则此变量会影响正则表达式中使用的字符类的处理以及-name 测试。此变量还会影响正则表达式中任何字符类的解释,该正则表达式用于解释对-ok 发出的提示的响应。`LC_CTYPE’环境变量也会影响打印文件名时哪些字符被认为是不可打印的请参阅“异常文件”部分;
LC_MESSAGES
确定用于国际化消息的区域设置。如果设置了“POSIXLY_CORRECT”环境变量,这也决定了对-ok 动作提示的响应的解释;
NLSPATH
确定国际化消息目录的位置;
PATH
影响搜索的目录以查找-exec,-execdir,-ok,-okdir 调用的可执行文件;
POSIXLY_CORRECT
确定-ls 和-fls 使用的块大小。如果设置了 POSIXLY_CORRECT,则块为 512 字节的单位。否则它们是 1024 字节的单位;
默认情况下,设置此变量也会关闭警告消息(即隐含-nowarn),因为 POSIX 要求除了-ok 的输出之外,在标准错误上打印的所有消息都是诊断消息,并且必须导致非零退出状态;
当未设置 POSIXLY_CORRECT 时,如果+zzz 不是有效的符号模式,则将-perm +zzz 视为-perm /zzz。设置 POSIXLY_CORRECT 时,此类构造将被视为错误;
设置 POSIXLY_CORRECT 时,-ok 操作对提示的响应将根据系统的消息目录进行解释,而不是根据 find 自己的消息转换进行解释;
TZ
影响用于-printf 和-fprintf 的某些与时间相关的格式指令的时区;
退出状态
0 成功
>0 失败。故意广泛描述。如果返回值不为零,则不应该依赖于查找结果的正确性。发生某些错误时,find 可能会立即停止,而不会完成指定的所有操作。例如,可能尚未检查某些起始点,或者可能尚未执行某些针对-exec … {} +或-execdir … {} +的挂起程序调用;
使用示例
在目录 / tmp 中或下面找到名为 core 的文件并删除它们。请注意,如果有任何包含换行符,单引号或双引号或空格的文件名,则此操作将无法正常工作;
在目录 /tmp 中或下面找到名为 core 的文件并删除它们,正确处理文件名包含单引号或双引号、空格、换行符的文件或目录名。-name 测试在-type 测试之前进行,以避免必须在每个文件上调用 stat(2);
在当前目录中或下面的每个文件上运行`file’。请注意,大括号用单引号括起来,以防止它们被解释为 shell 脚本标点符号。分号同样受到反斜杠的保护,但在这种情况下也可以使用单引号;
只遍历文件系统一次,将 SETUID 文件和目录列入 /root/suid.txt 中,将大文件列入 /root/big.txt 中;
搜索主目录中已在过去二十四小时内修改过的文件。此命令以这种方式工作,因为自上次修改每个文件以来的时间除以 24 小时,任何余数都将被丢弃。这意味着要匹配-mtime 0,文件必须在过去不到 24 小时之前进行修改;
搜索可执行但不可读的文件;
搜索对其所有者和组具有读写权限的文件,但其他用户可以读取但不能写入的文件。符合这些条件但设置了其他权限位的文件(例如,如果有人可以执行该文件)将不匹配:
搜索对其所有者和组具有读写权限以及其他用户可以读取的文件,而不考虑是否存在任何额外的权限位(例如可执行位)。例如,这将匹配具有模式 0777 的文件;
搜索某人(他们的所有者,他们的组,其他任何人)可写的文件;
所有这三个命令都做同样的事情,但第一个使用文件模式的八进制表示,另外两个使用符号形式。这些命令都搜索可由其所有者或其组写入的文件。匹配的文件的所有者和组不必都要可写入;
# find . -perm /u+w,g+w
# find . -perm /u=w,g=w
这两个命令都做同样的事情:搜索其所有者及其组可写的文件。:
# find . -perm -g+w,u+w
这两个命令都搜索每个人都可读的文件(-perm -444 或-perm -a+r),至少有设置一个写入位(-perm /222 或-perm /a+w),但对于任何人不可执行(分别是!-perm /111 和!-perm /a+x);
# find . -perm -a+r -perm /a+w \! -perm /a+x
此命令将 /source-dir 的内容复制到 /dest-dir,但省略名为.snapshot(及其中的任何内容)的文件和目录。它还省略了名称以~结尾但不包含其内容的文件或目录。构造-prune -o \( … -print0 \)非常常见。这里的想法是-prune 之前的表达式匹配要修剪的东西。但是,-prune 动作本身返回 true,因此以下-o 确保仅对那些未被修剪的目录评估右侧(修剪目录的内容甚至没有被访问,因此它们的内容无关紧要))。为清楚起见,-o 右侧的表达式在括号中,它强调-print0 动作仅发生在没有-prune 应用于它们的事物上。因为测试之间的默认“and”条件比-o 绑定得更紧密,所以这是默认值,但是括号有助于显示正在发生的事情;
# find . -name .snapshot -prune -o \( \! -name ‘*~’ -print0 \) | cpio -pmd0 /dest-dir
给定以下项目目录及其关联的 SCM 管理目录,执行项目根的高效搜索:
repo/project1/CVS
repo/gnu/project2/.svn
repo/gnu/project3/.svn
repo/gnu/project3/src/.svn
repo/project4/.git
在这个例子中,-prune 防止不必要的下降到已经发现的目录(例如我们不搜索 project3/src,因为我们已经找到了 project3/.svn),但是确保找到兄弟目录(project2 和 project3);
在目录 /tmp 中搜索文件、目录、符号链接,将这些类型作为逗号分隔列表(GNU 扩展名)传递:
# find /tmp \( -type f -o -type d -o -type l \)
第二个命令更长,但可移植更高;
相关手册
locate(1), locatedb(5), updatedb(1), xargs(1), chmod(1), fnmatch(3), regex(7), stat(2), lstat(2), ls(1), printf(3), strftime(3), ctime(3)
查看 find 的 Info 手册:info find
参考文献
man 1 find, Version 4.6.0+git+20161106-2
command – List of files where the line count is greater than 2 – Unix & Linux Stack Exchange
Linux find command: How to find files not matching a pattern | alvinalexander.com
bash – How to combine 2 -name conditions in find? – Unix & Linux Stack Exchange
linux – How to use regex with find command? – Stack Overflow
osx – find -delete does not delete non-empty directories – Unix & Linux Stack Exchange