find

在指定目录下查找文件

解释

从每个指定的起始点 (目录) 开始,搜索以该点为根的目录树,并按照运算符优先级规则从左至右评估给定的表达式,直到结果确定,此时find会继续处理下一个文件名。

补充说明

本文列出的选项指的是表达式列表中的选项。这些选项控制了find的行为,需在最后一个路径名之后立即指定。

五个真实选项: -H、-L、-P、-D 和 -O。如果出现,必须位于第一个路径名之前。关于这部分内容本文不做描述,具体内容可参考man7.org中的find

如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件,并且将查找到的子目录和文件全部进行显示。等效于以下命令:

find . -print

语法

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [起始点...] [表达式]

忽略真实选项后 (更为常见):

find [起始点...] [表达式]

表达式分类

起始点(列表)之后的部分是表达式。这是一种查询规范,描述了我们如何匹配文件(返回或者)以及对匹配到的文件进行何种操作。表达式由一系列元素组成:

表达式选项

测试选项

-amin<分钟>:查找在指定时间曾被存取过的文件或目录,单位以分钟计算;
-anewer<参考文件或目录>:查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录;
-atime<24小时数>:查找在指定时间曾被存取过的文件或目录,单位以24小时计算;
-cmin<分钟>:查找在指定时间之时被更改过的文件或目录;
-cnewer<参考文件或目录>查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录;
-ctime<24小时数>:查找在指定时间之时被更改的文件或目录,单位以24小时计算;
-empty:寻找文件大小为0 Byte的文件,或目录下没有任何子目录或文件的空目录;
-executable 匹配当前用户可执行的文件和可搜索的目录。
-false:将find指令的回传值皆设为False;
-fstype<文件系统类型>:只寻找该文件系统类型下的文件或目录;
-gid<群组识别码>:查找符合指定之群组识别码的文件或目录;
-group<群组名称>:查找符合指定之群组名称的文件或目录;
-ilname<范本样式>:此参数的效果和指定“-lname”参数类似,但忽略字符大小写的差别;
-iname<范本样式>:此参数的效果和指定“-name”参数类似,但忽略字符大小写的差别;
-inum<inode编号>:查找符合指定的inode编号的文件或目录;
-ipath<范本样式>:此参数的效果和指定“-path”参数类似,但忽略字符大小写的差别;
-iregex<范本样式>:此参数的效果和指定“-regexe”参数类似,但忽略字符大小写的差别;
-iwholename 模式参见`-ipath`。此选项的可移植性较`-ipath`差。
-links<连接数目>:查找符合指定的硬连接数目的文件或目录;
-lname<范本样式>:指定字符串作为寻找符号连接的范本样式;
-mmin<分钟>:查找在指定时间曾被更改过的文件或目录,单位以分钟计算;
-mtime<24小时数>:查找在指定时间曾被更改过的文件或目录,单位以24小时计算;
-name<范本样式>:指定字符串作为寻找文件或目录的范本样式;
-newer<参考文件或目录>:查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录;
-newerXY<引用>:如果正在考虑的文件的时间戳 X 比文件引用的时间戳 Y 更新则成功。
-nogroup:找出不属于本地主机群组识别码的文件或目录;
-nouser:找出不属于本地主机用户识别码的文件或目录;
-path<范本样式>:指定字符串作为寻找目录的范本样式;
-perm<权限数值>:查找符合指定的权限数值的文件或目录;
-readable:匹配当前用户可读的文件
-regex<范本样式>:指定字符串作为寻找文件或目录的范本样式;
-samefile 名称 文件与名称指向相同的 inode。
-size<文件大小>:查找符合指定的文件大小的文件;
-type<文件类型>:只寻找符合指定的文件类型的文件;
-uid<用户识别码>:查找符合指定的用户识别码的文件或目录;
-used<日数>:查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算;
-user<拥有者名称>:查找符和指定的拥有者名称的文件或目录;
-writable:匹配当前用户可写入的文件。
-xtype<文件类型>:此参数的效果和指定“-type”参数类似,差别在于它针对符号连接检查。
-context<表达式>:仅限 SELinux。文件的安全上下文与全局模式匹配

操作选项

-delete 删除文件或目录。

⚠️警告:find 命令会将命令行作为表达式进行解析,因此将-delete放在首位会将指定的起始点下的所有内容删除。且-delete操作无法删除一个目录,除非它是空的。

无参数
描述

如果删除成功则返回真。若删除失败,将显示错误消息,并且 find 最终退出时的状态码将为非零。

相关选项

-exec 执行命令

⚠️警告:使用-exec操作存在不可避免的安全问题,应改用-execdir选项。

参数

command ;command {} +

描述

如果返回状态为 0,则结果为真。注意:find 命令会将所有后续参数视为command的参数,直到遇到包含;的参数为止。字符串{}会在command的参数中所有出现的位置被替换为当前正在处理的文件名,而不仅仅是在它单独出现的参数中,这与某些版本的 find 不同。这两种结构可能需要使用反斜杠\或引号来转义,以防止被 shell 扩展。指定的命令会为每个匹配的文件运行一次。命令在起始目录中执行。

-execdir 在包含匹配文件的子目录中执行命令

参数

command ; | command {} +

描述

类似于-exec,但指定的command会在包含匹配文件的子目录中运行,而非find的起始点目录。与-exec一样,如果从shell调用find,{}应加引号。这是一种更安全的调用command方式,因为它避免了在解析匹配文件路径时出现的竞争条件。与-exec操作类似,+形式的-execdir会构建一个命令行来处理多个匹配文件,但任何给定的command调用只会列出存在于同一子目录中的文件。如果使用此选项,必须确保 PATH 环境变量未引用.,否则攻击者可以通过在您将运行-execdir的目录中留下一个适当命名的文件来运行任何命令。同样,PATH 中的条目不应为空非绝对目录名。如果使用+形式的任何调用以非零值作为退出状态返回,则 find 也会返回非零退出状态。如果 find 遇到错误,有时会导致立即退出,因此某些待处理的command可能根本不会运行。 操作结果取决于使用的是+还是;变体。-execdir command {} + 总是返回真,而 -execdir command {} ;仅在命令返回 0 时返回真。

-fls 创建文件并将结果写入文件

参数

file

描述

此选项始终返回真。-fls类似于-ls-fprint,但-fls会将结果写入文件中。无论谓词是否匹配,输出文件始终会被创建。有关文件名中特殊字符处理的信息,请参阅“特殊文件名处理”部分。

-fprint 将完整文件名打印到指定文件中

参数

file

描述

此选项始终返回真。若运行 find 时file不存在,则创建该file;若file已存在,则截断其内容。文件名/dev/stdout/dev/stderr有特殊处理,分别指向标准输出和标准错误输出。即使谓词从未匹配,输出文件也会始终创建。

-fprint0

参数

file

描述

此选项始终返回真。类似于-print0,但将输出写入文件;类似于-fprint。即使谓词从未匹配,输出文件也始终会被创建。

-fprintf

参数

file

描述

此选项始终返回真。类似于-printf,但将输出写入文件;类似于-fprint,即使谓词从未匹配,输出文件也会始终创建。

-ls 列出当前文件并输出到标准输出

无参数
描述

此选项始终返回真。以ls -dils格式列出当前文件并输出到标准输出。块计数为 1 KB 块,除非设置了环境变量 POSIXLY_CORRECT,此时使用 512 字节块。

-ok 执行命令前询问用户

参数

command ;

描述

类似于-exec,但首先会询问用户。如果用户同意,则运行该命令;否则仅返回 false。若运行该命令,其标准输入将被重定向至/dev/null。对提示的响应会与一对正则表达式进行匹配,以确定其为肯定或否定回答。若设置POSIXLY_CORRECT 环境变量,则该正则表达式从系统获取;否则,从 find 的消息翻译中获取。如果系统没有合适的定义,将使用 find 自身的定义。无论哪种情况,正则表达式本身的解释都会受到环境变量 LC_CTYPE(字符类)和 LC_COLLATE(字符范围和等价类)的影响。

相关选项

-okdir

参数

command ;

描述

类似于-execdir,但在执行前会以与-ok相同的方式询问用户。如果用户不同意,则直接返回 false。如果命令被执行,其标准输入将从/dev/null重定向。

相关选项

-print 打印完整文件名,后跟一个换行符

无参数
描述

此选项始终返回真。如果你将 find 的输出通过管道传输到另一个程序,并且你正在搜索的文件可能包含换行符,那么应该考虑使用-print0而不是-print

-print0 打印完整文件名,后跟一个空字符

无参数
描述

此选项始终返回真。包含换行符或其他类型空白字符的文件名能被正确解析,以便处理 find 输出的程序能正确理解。此选项对应于xargs-0选项。

-printf 打印格式

参数

format

可用的转义字符和指令包括:

描述

暂无

-prune 如果文件是目录,则不进入该目录

无参数
描述

此选项始终返回真。

相关选项

-quit 立即退出

无参数
描述

如果没有发生错误,则返回值为零。这与-prune 不同,因为-prune仅适用于被修剪目录的内容,而-quit则使 find 立即停止。不会有任何子进程继续运行。在程序退出之前,任何通过-exec ... +-execdir ... +构建的命令行都会被调用。执行-quit后,命令行中指定的文件将不再被处理。例如,find /tmp/foo /tmp/bar -print -quit将仅打印 /tmp/foo-quit的一个常见用途是在找到所需内容后停止搜索文件系统。

全局选项

始终返回真值。全局选项对命令行中较早出现的测试也会生效。为避免混淆,全局选项应在命令行上列出起始点之后、第一个测试选项、位置选项或操作选项之前指定。若在其他位置指定全局选项,find 会发出警告消息,说明这可能引起混淆。

全局选项出现在起始点列表之后,因此与例如-L 这样的选项不属于同一类别。

-d -depth的同义词

无参数
描述

仅用于与 FreeBSD、NetBSD、MacOS X 和 OpenBSD 兼容。

-depth 遍历级别

参数

levels

描述

在处理目录本身之前,先处理目录中的内容。-delete操作也隐含了-depth

-files0-from 从文件中读取起始点,而非通过命令行获取。

参数

file

描述

使用此选项可以安全地给 find 命令传递任意数量的起始点。使用此选项和在命令行中传递起始点是互斥的,因此不允许同时进行。文件参数是强制性的。文件中的起始点必须用 ASCII NUL 字符分隔。两个连续的 NUL 字符,即带有零长度文件名的起始点是不允许的,这将导致错误诊断,并随后产生非零退出码。

与标准调用不同,在标准调用中,如果没有传递路径参数,find 会默认将当前目录作为起始点。起始点的处理方式与其他情况相同,例如,find 命令会递归进入子目录,除非另有阻止。若要仅处理起始点,可以额外传递-maxdepth 0参数。

其他说明:如果一个文件在输入文件中被列出多次,则其是否会被多次访问未作规定。如果在查找操作期间文件被修改,结果同样未作规定。最后,find 退出时(无论是通过-quit还是其他方式),命名文件中的查找位置也未作规定。此处未作规定意味着它可能有效也可能无效或者不做任何特定的事情,并且该行为可能因平台或 findutils 版本而异。

💡可以使用-files0-from从标准输入流中读取起始点列表,例如从管道中读取。在这种情况下,不允许使用-ok-okdir操作,因为它们会干扰从标准输入读取以获取用户确认。

⚠️警告:如果给定文件为空,find 不会处理任何起始点,因此在解析完程序参数后会立即退出。

-help 和 --help 打印 find 命令行用法的摘要并退出。

无参数
描述

无描述

-ignore_readdir_race

无参数
描述

通常情况下,当 find 无法对文件进行状态检查(stat)时,会发出错误消息。如果您启用此选项,并且在 find 从目录读取文件名,到尝试进行状态检查之间的时间内文件被删除,则不会发出任何错误消息。这也适用于命令行中指定的文件或目录。此选项在命令行读取时生效,这意味着您不能在文件系统的某部分启用此选项,而在另一部分禁用它(如果需要这样做,您需要发出两个 find 命令,一个启用选项,一个不启用)。此外,使用-ignore_readdir_race选项时,如果在读取父目录后文件已消失,find 命令将忽略-delete操作的错误:它不会输出错误诊断信息,并且-delete操作的返回码将为真。

-maxdepth 最大遍历级别

参数

levels

描述

最多向下遍历 levels 级(一个非负整数)目录层级。使用-maxdepth 0表示仅对起始点本身应用测试和操作。

-mindepth 最小遍历级别

参数

levels

描述

在小于指定级别(非负整数)的层级上不执行任何测试或操作。使用-mindepth 1表示处理除起始点外的所有文件

-mount 不在其他文件系统中下降目录

无参数
描述

这是-xdev的替代名称,用于与其他一些版本的 find 兼容。

-noignore_readdir_race

无参数
描述

关闭了-ignore_readdir_race的效果。

-noleaf 不进行优化。

无参数
描述

不通过假设目录包含比其硬链接数少 2 个子目录来进行优化。在搜索不遵循 Unix 目录链接惯例的文件系统时,需要此选项,例如 CD-ROM、MS-DOS 文件系统或 AFS 卷挂载点。在正常的 Unix 文件系统上,每个目录至少有 2 个硬链接:其名称及其.条目。此外,其子目录(如果有)各自有一个指向该目录的..条目。当 find 检查一个目录时,在它已经统计了比目录链接数少 2 个子目录之后,它知道该目录中的其余条目是非目录(目录树中的“叶”文件)。如果只需要检查文件的名称,则无需对其进行状态检查;这可以显著提高搜索速度。

-version 和 --version 打印 find 的版本号并退出。

无参数
描述

无描述

-xdev 不进入其他文件系统的目录。

无参数
描述

无描述

位置选项

始终返回真值。它们仅影响命令行中后续的测试。

-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 文档解释了各种正则表达式类型的含义及其差异。如果您不使用此选项,find 的行为如同已指定正则表达式类型为emacs

-warn 和 -nowarn 开启或关闭警告消息。

无参数
描述

这些警告仅适用于命令行使用,不适用于 find 在搜索目录时可能遇到的情况。默认行为是:如果标准输入是tty,则对应-warn;否则对应-nowarn。如果产生与命令行使用相关的警告消息,find 的退出状态不受影响。如果设置了 POSIXLY_CORRECT 环境变量,并且也使用了-warn,则未指定哪些(如果有)警告会被激活。

运算符选项

运算符按优先级递减顺序列出:

💡提示:当-a隐式指定(例如两个测试之间没有显式运算符)或显式指定时,其优先级高于-o。例如,find . -name foo -o -name bar -print永远不会打印foo

-not

参数

expr

描述

等同于! expr,但不符合 POSIX 标准。

-a

参数

expr1 -a expr2

描述

两个连续的表达式被视为隐含地用-a连接;如果expr1为假,则不评估expr2。等同于expr1 expr2

-and

参数

expr1 -and expr2

描述

-a相同。但不符合 POSIX 标准。

-o

参数

expr1 -o expr2

描述

expr1expr2始终都会被评估。expr1的值会被丢弃;列表的值即为expr2的值。逗号运算符(,)在搜索多种不同类型的事物时非常有用,但只会遍历文件系统层次结构一次。-fprintf动作可用于将各种匹配项列出到多个不同的输出文件中。若expr1为真,则不评估expr2

-or

参数

expr1 -or expr2

描述

-o相同。但不符合 POSIX 标准。

例子

当前目录搜索所有文件,且文件内容包含 “140.206.111.111”

find . -type f -name "*" | xargs grep "140.206.111.111"

根据文件或者正则表达式进行匹配

列出当前目录及子目录下所有文件和文件夹

find .

/home目录下查找以.txt结尾的文件名

find /home -name "*.txt"

同上,但忽略大小写

find /home -iname "*.txt"

当前目录及子目录下查找所有以.txt和.pdf结尾的文件

find . \( -name "*.txt" -o -name "*.pdf" \)


find . -name "*.txt" -o -name "*.pdf"

匹配文件路径或者文件

find /usr/ -path "*local*"

基于正则表达式匹配文件路径

find . -regex ".*\(\.txt\|\.pdf\)$"

同上,但忽略大小写

find . -iregex ".*\(\.txt\|\.pdf\)$"

否定参数

找出/home下不是以.txt结尾的文件

find /home ! -name "*.txt"

根据文件类型进行搜索

find . -type 类型参数

类型参数列表:

基于目录深度搜索

向下最大深度限制为3

find . -maxdepth 3 -type f

搜索出深度距离当前目录至少2个子目录的所有文件

find . -mindepth 2 -type f

根据文件时间戳进行搜索

find . -type f 时间戳

UNIX/Linux文件系统每个文件都有三种时间戳:

搜索最近七天内被访问过的所有文件

find . -type f -atime -7

搜索恰好在七天前被访问过的所有文件

find . -type f -atime 7

搜索超过七天内被访问过的所有文件

find . -type f -atime +7

搜索访问时间超过10分钟的所有文件

find . -type f -amin +10

找出比file.log修改时间更长的所有文件

find . -type f -newer file.log

根据文件大小进行匹配

find . -type f -size 文件大小单元

文件大小单元:

搜索大于10KB的文件

find . -type f -size +10k

搜索小于10KB的文件

find . -type f -size -10k

搜索等于10KB的文件

find . -type f -size 10k

删除匹配文件

删除当前目录下所有.txt文件

find . -type f -name "*.txt" -delete

根据文件权限/所有权进行匹配

当前目录下搜索出权限为777的文件

find . -type f -perm 777

找出当前目录下权限不是644的php文件

find . -type f -name "*.php" ! -perm 644

找出当前目录用户tom拥有的所有文件

find . -type f -user tom

找出当前目录用户组sunk拥有的所有文件

find . -type f -group sunk

借助-exec选项与其他命令结合使用

找出当前目录下所有root的文件,并把所有权更改为用户tom

find .-type f -user root -exec chown tom {} \;

上例中, {} 用于与 -exec 选项结合使用来匹配所有文件,然后会被替换为相应的文件名。

找出自己家目录下所有的.txt文件并删除

find $HOME/. -name "*.txt" -ok rm {} \;

上例中, -ok-exec 行为一样,不过它会给出提示,是否执行相应的操作。

查找当前目录下所有.txt文件并把他们拼接起来写入到all.txt文件中

find . -type f -name "*.txt" -exec cat {} \;> /all.txt

将30天前的.log文件移动到old目录中

find . -type f -mtime +30 -name "*.log" -exec cp {} old \;

找出当前目录下所有.txt文件并以“File:文件名”的形式打印出来

find . -type f -name "*.txt" -exec printf "File: %s\n" {} \;

因为单行命令中-exec参数中无法使用多个命令,以下方法可以实现在-exec之后接受多条命令

-exec ./text.sh {} \;

搜索但跳过指定的目录

查找当前目录或者子目录下所有.txt文件,但是跳过子目录sk

find . -path "./sk" -prune -o -name "*.txt" -print

⚠️ ./sk 不能写成 ./sk/ ,否则没有作用。

忽略两个目录

find . \( -path ./sk -o  -path ./st \) -prune -o -name "*.txt" -print

⚠️ 如果写相对路径必须加上./

find其他技巧收集

要列出所有长度为零的文件

find . -empty

其它实例

find ~ -name '*jpg' # 主目录中找到所有的 jpg 文件。 -name 参数允许你将结果限制为与给定模式匹配的文件。
find ~ -iname '*jpg' # -iname 就像 -name,但是不区分大小写
find ~ ( -iname 'jpeg' -o -iname 'jpg' ) # 一些图片可能是 .jpeg 扩展名。幸运的是,我们可以将模式用“或”(表示为 -o)来组合。
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f # 如果你有一些以 jpg 结尾的目录呢? (为什么你要命名一个 bucketofjpg 而不是 pictures 的目录就超出了本文的范围。)我们使用 -type 参数修改我们的命令来查找文件。
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type d # 也许你想找到那些命名奇怪的目录,以便稍后重命名它们

最近拍了很多照片,所以让我们把它缩小到上周更改的文件

find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7

你可以根据文件状态更改时间 (ctime)、修改时间 (mtime) 或访问时间 (atime) 来执行时间过滤。 这些是在几天内,所以如果你想要更细粒度的控制,你可以表示为在几分钟内(分别是 cmin、mmin 和 amin)。 除非你确切地知道你想要的时间,否则你可能会在 + (大于)或 - (小于)的后面加上数字。

但也许你不关心你的照片。也许你的磁盘空间不够用,所以你想在 log 目录下找到所有巨大的(让我们定义为“大于 1GB”)文件:

find /var/log -size +1G

或者,也许你想在 /data 中找到 bcotton 拥有的所有文件:

find /data -owner bcotton

你还可以根据权限查找文件。也许你想在你的主目录中找到对所有人可读的文件,以确保你不会过度分享。

find ~ -perm -o=r

删除 mac 下自动生成的文件

find ./ -name '__MACOSX' -depth -exec rm -rf {} \;

统计代码行数

find . -name "*.java"|xargs cat|grep -v ^$|wc -l # 代码行数统计, 排除空行