在指定目录下查找文件
从每个指定的起始点 (目录) 开始,搜索以该点为根的目录树,并按照运算符优先级规则从左至右评估给定的表达式,直到结果确定,此时find
会继续处理下一个文件名。
本文列出的选项指的是表达式列表中的选项。这些选项控制了find
的行为,需在最后一个路径名之后立即指定。
五个真实选项: -H、-L、-P、-D 和 -O
。如果出现,必须位于第一个路径名之前。关于这部分内容本文不做描述,具体内容可参考man7.org中的find
如果使用该命令时,不设置任何参数,则find
命令将在当前目录下查找子目录与文件,并且将查找到的子目录和文件全部进行显示。等效于以下命令:
find . -print
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [起始点...] [表达式]
忽略真实选项后 (更为常见):
find [起始点...] [表达式]
起始点(列表)之后的部分是表达式。这是一种查询规范,描述了我们如何匹配文件(返回真或者假)以及对匹配到的文件进行何种操作。表达式由一系列元素组成:
-empty
测试仅在当前文件为空时为真。-print
操作会在标准输出上打印当前文件的名称。-depth
选项使find以深度优先的顺序遍历文件系统。-regextype
选项是位置选项,用于指定命令行中后续正则表达式所使用的正则表达式方言。-o
(表示逻辑或)和-a
(表示逻辑与)。如果缺少运算符,则默认使用-a
。-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。文件的安全上下文与全局模式匹配
⚠️警告:find 命令会将命令行作为表达式进行解析,因此将
-delete
放在首位会将指定的起始点下的所有内容删除。且-delete
操作无法删除一个目录,除非它是空的。
如果删除成功则返回真。若删除失败,将显示错误消息,并且 find 最终退出时的状态码将为非零。
-delete
操作会自动启用-depth
选项。为了避免意外情况,通常最好在早期的Tests选项中明确使用-depth
选项。-depth
会使-prune
失效,因此-delete
操作无法与-prune
有效结合使用。通常,用户可能希望在实际删除操作前,先用带有-print
的查找命令行进行测试,以确保在添加-delete
进行实际删除时不会出现意外结果。-delete
与此选项一起使用时,find 会忽略自父目录读取以来文件已消失的情况下-delete
操作的错误:它不会输出错误诊断,不会将退出代码更改为非零,并且-delete
操作的返回代码将为真。⚠️警告:使用
-exec
操作存在不可避免的安全问题,应改用-execdir
选项。
command ;
或 command {} +
如果返回状态为 0,则结果为真。注意:find 命令会将所有后续参数视为command
的参数,直到遇到包含;
的参数为止。字符串{}
会在command
的参数中所有出现的位置被替换为当前正在处理的文件名,而不仅仅是在它单独出现的参数中,这与某些版本的 find 不同。这两种结构可能需要使用反斜杠\
或引号来转义,以防止被 shell 扩展。指定的命令会为每个匹配的文件运行一次。命令在起始目录中执行。
command ;
| command {} +
类似于-exec
,但指定的command
会在包含匹配文件的子目录中运行,而非find的起始点目录。与-exec
一样,如果从shell调用find,{}
应加引号。这是一种更安全的调用command
方式,因为它避免了在解析匹配文件路径时出现的竞争条件。与-exec
操作类似,+
形式的-execdir
会构建一个命令行来处理多个匹配文件,但任何给定的command
调用只会列出存在于同一子目录中的文件。如果使用此选项,必须确保 PATH 环境变量未引用.
,否则攻击者可以通过在您将运行-execdir
的目录中留下一个适当命名的文件来运行任何命令。同样,PATH 中的条目不应为空或非绝对目录名。如果使用+
形式的任何调用以非零值作为退出状态返回,则 find 也会返回非零退出状态。如果 find 遇到错误,有时会导致立即退出,因此某些待处理的command可能根本不会运行。 操作结果取决于使用的是+
还是;
变体。-execdir command {} +
总是返回真,而 -execdir command {} ;
仅在命令返回 0 时返回真。
file
此选项始终返回真。-fls
类似于-ls
和-fprint
,但-fls
会将结果写入文件中。无论谓词是否匹配,输出文件始终会被创建。有关文件名中特殊字符处理的信息,请参阅“特殊文件名处理”部分。
file
此选项始终返回真。若运行 find 时file
不存在,则创建该file
;若file
已存在,则截断其内容。文件名/dev/stdout
和/dev/stderr
有特殊处理,分别指向标准输出和标准错误输出。即使谓词从未匹配,输出文件也会始终创建。
file
此选项始终返回真。类似于-print0
,但将输出写入文件;类似于-fprint
。即使谓词从未匹配,输出文件也始终会被创建。
file
此选项始终返回真。类似于-printf
,但将输出写入文件;类似于-fprint
,即使谓词从未匹配,输出文件也会始终创建。
此选项始终返回真。以ls -dils
格式列出当前文件并输出到标准输出。块计数为 1 KB 块,除非设置了环境变量 POSIXLY_CORRECT,此时使用 512 字节块。
command ;
类似于-exec
,但首先会询问用户。如果用户同意,则运行该命令;否则仅返回 false。若运行该命令,其标准输入将被重定向至/dev/null
。对提示的响应会与一对正则表达式进行匹配,以确定其为肯定或否定回答。若设置POSIXLY_CORRECT 环境变量,则该正则表达式从系统获取;否则,从 find 的消息翻译中获取。如果系统没有合适的定义,将使用 find 自身的定义。无论哪种情况,正则表达式本身的解释都会受到环境变量 LC_CTYPE(字符类)和 LC_COLLATE(字符范围和等价类)的影响。
-ok
同时指定。command ;
类似于-execdir
,但在执行前会以与-ok
相同的方式询问用户。如果用户不同意,则直接返回 false。如果命令被执行,其标准输入将从/dev/null
重定向。
-okdir
同时指定。此选项始终返回真。如果你将 find 的输出通过管道传输到另一个程序,并且你正在搜索的文件可能包含换行符,那么应该考虑使用-print0
而不是-print
。
此选项始终返回真。包含换行符或其他类型空白字符的文件名能被正确解析,以便处理 find 输出的程序能正确理解。此选项对应于xargs
的-0
选项。
format
可用的转义字符和指令包括:
\
。\
后跟任何其他字符,都会被视为普通字符,因此它们都会被打印出来。暂无
此选项始终返回真。
-depth
,那么-prune
将无效。-delete
隐含了-depth
,所以不能有效地同时使用两者。如果没有发生错误,则返回值为零。这与-prune
不同,因为-prune
仅适用于被修剪目录的内容,而-quit
则使 find 立即停止。不会有任何子进程继续运行。在程序退出之前,任何通过-exec ... +
或-execdir ... +
构建的命令行都会被调用。执行-quit
后,命令行中指定的文件将不再被处理。例如,find /tmp/foo /tmp/bar -print -quit
将仅打印 /tmp/foo
。-quit
的一个常见用途是在找到所需内容后停止搜索文件系统。
始终返回真值。全局选项对命令行中较早出现的测试也会生效。为避免混淆,全局选项应在命令行上列出起始点之后、第一个测试选项、位置选项或操作选项之前指定。若在其他位置指定全局选项,find 会发出警告消息,说明这可能引起混淆。
全局选项出现在起始点列表之后,因此与例如
-L
这样的选项不属于同一类别。
-depth
的同义词仅用于与 FreeBSD、NetBSD、MacOS X 和 OpenBSD 兼容。
levels
在处理目录本身之前,先处理目录中的内容。-delete
操作也隐含了-depth
。
file
使用此选项可以安全地给 find 命令传递任意数量的起始点。使用此选项和在命令行中传递起始点是互斥的,因此不允许同时进行。文件参数是强制性的。文件中的起始点必须用 ASCII NUL 字符分隔。两个连续的 NUL 字符,即带有零长度文件名的起始点是不允许的,这将导致错误诊断,并随后产生非零退出码。
与标准调用不同,在标准调用中,如果没有传递路径参数,find 会默认将当前目录作为起始点。起始点的处理方式与其他情况相同,例如,find 命令会递归进入子目录,除非另有阻止。若要仅处理起始点,可以额外传递-maxdepth 0
参数。
其他说明:如果一个文件在输入文件中被列出多次,则其是否会被多次访问未作规定。如果在查找操作期间文件被修改,结果同样未作规定。最后,find 退出时(无论是通过-quit
还是其他方式),命名文件中的查找位置也未作规定。此处未作规定意味着它可能有效也可能无效,或者不做任何特定的事情,并且该行为可能因平台或 findutils 版本而异。
💡可以使用
-files0-from
从标准输入流中读取起始点列表,例如从管道中读取。在这种情况下,不允许使用-ok
和-okdir
操作,因为它们会干扰从标准输入读取以获取用户确认。
⚠️警告:如果给定文件为空,find 不会处理任何起始点,因此在解析完程序参数后会立即退出。
无描述
通常情况下,当 find 无法对文件进行状态检查(stat)时,会发出错误消息。如果您启用此选项,并且在 find 从目录读取文件名,到尝试进行状态检查之间的时间内文件被删除,则不会发出任何错误消息。这也适用于命令行中指定的文件或目录。此选项在命令行读取时生效,这意味着您不能在文件系统的某部分启用此选项,而在另一部分禁用它(如果需要这样做,您需要发出两个 find 命令,一个启用选项,一个不启用)。此外,使用-ignore_readdir_race
选项时,如果在读取父目录后文件已消失,find 命令将忽略-delete
操作的错误:它不会输出错误诊断信息,并且-delete
操作的返回码将为真。
levels
最多向下遍历 levels 级(一个非负整数)目录层级。使用-maxdepth 0
表示仅对起始点本身应用测试和操作。
levels
在小于指定级别(非负整数)的层级上不执行任何测试或操作。使用-mindepth 1
表示处理除起始点外的所有文件。
这是-xdev
的替代名称,用于与其他一些版本的 find 兼容。
关闭了-ignore_readdir_race
的效果。
不通过假设目录包含比其硬链接数少 2 个子目录来进行优化。在搜索不遵循 Unix 目录链接惯例的文件系统时,需要此选项,例如 CD-ROM、MS-DOS 文件系统或 AFS 卷挂载点。在正常的 Unix 文件系统上,每个目录至少有 2 个硬链接:其名称及其.
条目。此外,其子目录(如果有)各自有一个指向该目录的..
条目。当 find 检查一个目录时,在它已经统计了比目录链接数少 2 个子目录之后,它知道该目录中的其余条目是非目录(目录树中的“叶”文件)。如果只需要检查文件的名称,则无需对其进行状态检查;这可以显著提高搜索速度。
无描述
无描述
始终返回真值。它们仅影响命令行中后续的测试。
用于
-amin
、-atime
、-cmin
、-ctime
、-mmin
和-mtime
从今天开始而非从 24 小时前开始。此选项仅影响命令行中后续出现的测试。
已弃用,请改用-L
选项。隐含-noleaf
。-follow
选项仅影响命令行中出现在其后的那些测试。除非已指定-H
或-L
选项,否则-follow
选项的位置会改变-newer
谓词的行为;作为-newer
参数列出的任何文件,如果它们是符号链接,则会被解引用。同样的情况适用于-newerXY
、-anewer
和-cnewer
。类似地,-type
谓词将始终匹配符号链接所指向的文件类型,而非链接本身。使用-follow
会导致 -lname
和-ilname
谓词始终返回 false。
type
更改-regex
和-iregex
测试在命令行后续部分所理解的正则表达式语法。要查看已知的正则表达式类型,请使用-regextype help
。Texinfo 文档解释了各种正则表达式类型的含义及其差异。如果您不使用此选项,find 的行为如同已指定正则表达式类型为emacs
。
这些警告仅适用于命令行使用,不适用于 find 在搜索目录时可能遇到的情况。默认行为是:如果标准输入是tty
,则对应-warn
;否则对应-nowarn
。如果产生与命令行使用相关的警告消息,find 的退出状态不受影响。如果设置了 POSIXLY_CORRECT 环境变量,并且也使用了-warn
,则未指定哪些(如果有)警告会被激活。
运算符按优先级递减顺序列出:
(expr)
强制优先级。由于括号对 shell 有特殊含义,通常需要对它们进行引用。许多示例为此使用了反斜杠:\(...\)
而非 (...)
。! expr
若表达式为假则结果为真(取反)。此字符通常也需要防止被 shell 解释。💡提示:当
-a
隐式指定(例如两个测试之间没有显式运算符)或显式指定时,其优先级高于-o
。例如,find . -name foo -o -name bar -print
永远不会打印foo
。
expr
等同于! expr
,但不符合 POSIX 标准。
expr1
-a expr2
两个连续的表达式被视为隐含地用-a
连接;如果expr1
为假,则不评估expr2
。等同于expr1 expr2
。
expr1
-and expr2
与-a
相同。但不符合 POSIX 标准。
expr1
-o expr2
expr1
和expr2
始终都会被评估。expr1
的值会被丢弃;列表的值即为expr2
的值。逗号运算符(,
)在搜索多种不同类型的事物时非常有用,但只会遍历文件系统层次结构一次。-fprintf
动作可用于将各种匹配项列出到多个不同的输出文件中。若expr1
为真,则不评估expr2
。
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 . -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 # 代码行数统计, 排除空行