find

检索系统中的文件


语法格式

find [-H|-L|-P] [paths] [expression]
find [--help] [--version]

命令简介

find命令主要用于检索系统中的文件,以指定的条件表达式(文件名、文件大小及文件修改日期等文件属性)为匹配准则,从指定的目录开始,逐层深入各级子目录,递归地检索匹配表达式的所有文件。

“-H”、“-L”和“-P”选项主要用于控制如何处理符号链接文件。如果存在,必须出现在第一个路径名之前。紧随其后的paths是需要考察的目录,作为文件检索的起点。目录路径名后面的expression是选择表达式,用于指定各种匹配准则或检索条件。

命令选项

-P  仅限定于符号链接文件本身,而不考虑其引用的文件,这是find命令默认的处理方式。当find考察和处理文件且文件是一个符号链接文件时,依据符号链接文件本身的属性信息进行选择。

-L  总是跟随符号链接文件的指向,进一步考察和处理其引用的文件。当find考察和处理文件且文件是一个符号链接文件时,应依据符号链接文件引用文件的属性信息进行选择(除非符号链接文件引用的文件不存在或无法考察)。在检索期间,当find发现一个指向某个子目录的符号链接文件时,需要进一步检索子目录。当“-type”与“-L”选项一起使用时,总是按照符号链接文件引用文件的类型进行匹配和选择,除非符号链接文件引用的文件不存在。“-L”选项总是引起“-lname”和“-ilname”测试返回假。

-H  仅限于符号链接文件本身,而不考虑其引用的文件,除非处理的是命令行的文件参数。当find考察和处理文件且文件是一个符号链接文件时,依据符号链接文件本身的属性信息进行选择。唯一的例外是当命令行指定的文件参数是一个符号链接文件时,需跟随符号链接文件的指向,进一步考察和处理其引用的文件。如果命令行文件参数是一个符号链接文件且其引用的是一个目录,将考察和处理目录中的文件(除非指定了“-maxdepth 0”选项)。如果符号链接文件引用的文件无法考察,可退而考察符号链接文件本身的属性信息。

通常,“-H”、“-L”和“-P”选项原则上不能同时存在。如果命令行上同时指定了其中的两个或三个选项,则只有最后一个选项有效。此外,“-P”是默认的选项,除非又指定了“-H”或“-L”选项,通常总是以“-P”为准。

表达式

表达式由各种选项(影响find命令的整体操作而非特定文件的处理,且总是返回真)、测试(返回真或假)和动作(执行特定的处理,且返回真或假)等组成,经由逻辑运算符组合在一起,形成一个完整的表达式。如果省略了运算符,默认的运算符是“-and”。

当表达式中没有明确指定任何动作(“-prune”动作除外)时,如果表达式的测试结果为真,对选出的文件总是执行“-print”动作。

选项

所有表达式选项总是返回真。除了“-follow”和“-regextype”等,表达式选项影响所有的测试,这是因为在解析命令行选项与参数时,find首先处理表达式选项,但直至开始考察文件时,才会用到测试条件。“-follow”和“-regextype”选项仅影响命令行中出现在其后的测试条件,故为清晰起见,必要时最好把这个选项置于表达式的开始位置,否则会输出一个警告信息。

-depth  表示逐层深入各级子目录,采用先文件后目录的方式,自底向上依次检索所有的文件和目录。注意,“-delete”动作也蕴含着“-depth”动作。

-help, --help  显示命令行用法的概要说明,然后正常退出。

-follow  即将作废,取而代之的是“-L”选项。两者均表示考察和处理符号链接文件引用的文件。唯一的差别是:“-L”是全局选项,“-follow”仅在从出现的位置开始发挥作用。

-maxdepth levels  最多深入命令行参数下面指定层次的子目录。例如,“-maxdepth 0”意味着仅仅测试和处理命令行参数。

-mindepth levels  禁止测试或处理小于指定层次的任何文件或目录。例如,“-mindepth 1”意味着不考虑命令行参数本身,仅处理其下面的所有子目录及文件。

-mount  禁止深入其他文件系统中的目录。另外一个等同的选项“-xdev”主要是考虑到与其他某些版本的find命令的兼容性而增加的。

-regextype type  指定“-regex”或“-iregex”测试采用的正则表达式类型。当前支持的正则表达式包括emacs(默认)、posix-awk、posix-basic、posix-egrep和posix-extended。

-version, --version  显示命令的版本与作者等信息,然后正常退出。

-warn, -nowarn  开关警告信息的显示。这些警告仅适用于命令行的用法,而非find在检索目录和文件时遇到的其他情况。如果标准输入是终端,“-warn”是默认的选择,否则选择“-nowarn”。

-xautofs  禁止深入autofs文件系统中的目录。

-xdev  禁止深入其他文件系统中的目录。

测试

通常,测试由关键字与参数组成。当参数是一个数字时,前面可以插入一个加号“+”或减号“-”,分别表示大于或小于指定的数量,否则表示恰好等于指定的数量。

-amin [±]n  选择最近访问时间在n分钟之前、n分钟之内或恰好n分钟时的文件。

-anewer file  选择最近访问时间比指定文件更新的文件。如果指定的文件是符号链接文件,且同时指定了“-H”或“-L”选项,以其引用文件的最近访问时间为准。

-atime [±]n  选择最近访问时间在n天之前、n天之内或恰好n天时的文件。

-cmin [±]n  选择信息节点最近状态改变时间在n分钟之前、n分钟之内或恰好n分钟时的文件。

-cnewer file  选择信息节点最近状态改变时间比指定文件更新的文件。如果指定的文件是符号链接文件,且同时指定了“-H”或“-L”选项,以其引用文件的最近状态改变时间为准。

-ctime [±]n  选择信息节点最近状态改变时间在n天之前、n天之内或恰好n天时的文件。

-empty  文件为空,且为普通文件或目录。

-executable  选择可执行文件和能够检索的目录。这个测试的主要目的是要充分考虑访问控制表以及“-perm”测试忽略的其他访问权限。

-fstype type  选择位于指定文件系统类型中的文件。

-gid [±]n  选择匹配指定用户组ID的文件。

-group grpname  选择匹配指定用户组的文件。其中,grpname可以是用户组名,也可以是用户组ID号。

-ilname pattern  类似于“-lname”,但严格区别大小写字母。如果同时指定了“-L”或“-follow”选项,这个测试将会返回假,除非符号链接文件对应的文件不存在。

-iname pattern  类似于“-name”,但不区别大小写字母。例如,文件名模式“fo*”或“FO?”均能匹配foo、Foo或FOO等文件。与Shell的文件名扩展不同,在这里的模式中,星号“*”能够匹配文件名首字符的句点“.”。例如,“find -name "*bar"”命令能够检索出“.foobar”文件。注意,用户应当在这样的模式前后加引号,以免Shell首先解析任何通配符。

-inum [±]n  选择匹配指定信息节点号的文件。

-iregex pattern  类似于“-regex”,但不区别大小写字母。

-links [±]n  选择硬链接计数大于、等于或小于n的文件。

-lname pattern  选择其文件内容(即引用的文件)匹配指定文件名模式的符号链接文件。模式中的元字符能够像处理普通字符一样匹配“/”或“.”等字符。如果指定了“-L”选项,这个测试总是返回假,除非符号链接文件引用的文件不存在。

-mmin [±]n  选择最近修改时间在n分钟之前、n分钟之内或恰好n分钟时的文件。

-mtime [±]n  选择最近修改时间在n天之前、n天之内或恰好n天时的文件。

-name pattern  选择匹配指定文件名模式的文件。选择时以文件名为准,不考虑目录部分,也就是说,只要文件名本身匹配即可。如果指定的文件名中含有通配符“*”、“?”或“[…]”,文件名前后应加单引号或双引号。也可以在通配符前加转义符号“\”。注意,在新版的find命令中,通配符适用于文件名首字符为句点“.”的隐藏文件。

-newer file  选择最近修改时间比指定文件更新的文件。如果指定的文件是一个符号链接文件,且同时指定了“-H”或“-L”选项,以其引用文件的最近修改时间为准。

-newerXY ref  以指定参数ref的时间属性为参照,选择比参照时间更新的文件。参数ref通常是一个文件,可以选取其不同的时间属性作为比较的参照时间,也可以是一个描述绝对时间的字符串(如2012-01-22 10:20:30,参见date命令的“-d”选项)。XY(表示参照文件的时间类型)可以是下列字母之一,说明使用哪一种时间作为参考时间。

a  表示参考文件的访问时间。
B  表示参考文件的创建时间。
c  表示参考文件信息节点的状态改变时间。
m  表示参考文件的修改时间。
t  把ref参数直接解释成一个时间。
例如,“-newermt 2012-12-22 00:00:00”测试条件表示选择在2012年12月22日之后修改过的文件。注意,上述字母不能任意组合,其中的某些组合是不合法的,如X不能是t。

-nogroup  检索其用户组名并未在/etc/group文件中定义的文件,即检索不属于本地系统用户组的文件。

-nouser  检索其文件属主并未在/etc/passwd文件中定义的文件,即检索非本地系统用户的文件。

-path pattern  选择其文件名匹配指定Shell模式的文件。此外,模式中的元字符能够像处理普通字符一样匹配“/”或“.”等字符。例如,“find . -path "./sr*sc"”命令能够检索出“./src/misc”(如果存在)。注意,“-path”指定的模式匹配测试是从命令行中指定目录开始的整个文件路径名。

-perm mode  选择其访问权限严格匹配指定模式的文件,也就是说,选择的文件必须完全匹配mode定义的所有访问权限。其中的mode可以用八进制数值表示,也可以采用符号形式,如u(文件属主)、g(用户组)、o(其他用户)和a(所有用户),其用法同chmod命令。注意,因为这里要求严格匹配,使用符号形式表示起来比较复杂,故最好采用八进制数值。

-perm -mode  选择其访问权限包括指定模式mode定义的所有访问权限的文件。mode既可以是八进制数值表示,也可以采用符号形式。注意,这里指定的访问权限只是最低要求,是一个大于等于的问题,不需要严格匹配。

-perm /mode  选择其访问权限满足指定模式中任何一种访问权限要求的文件,即只要符合mode定义的任何一种访问权限要求即可,这是一个小于等于的问题。mode既可以用八进制数值表示,也可以采用符号形式。如果指定的mode为“/000”,意味着任何文件均符合要求(这也相当于“-perm -000”)。

-readable  选择可读的文件。这个测试的主要目的是要充分考虑访问控制表以及“-perm”测试忽略的其他访问权限。

-regex pattern  选择其路径名匹配指定正则表达式模式的文件。这是一种完整路径名的匹配,而非检索。例如,为了匹配一个名为“./fubar3”的文件,必须使用正则表达式“.*bar.”或“.*b.*3”,而非“f.*r3”。通常,find命令能够理解的正则表达式是emacs正则表达式,但可以使用“-regextype”选项改换其他正则表达式。

-samefile name  选择其与指定文件名引用同一信息节点的文件。如果指定了“-L”选项,这个测试条件也适用于符号链接文件。

-size [±]n[cwbkMG]  选择大于、小于或等于指定数据块(512字节)数量的文件。如果n后面附加一个字符c、w、b、k、M或G,则分别表示指定的文件大小以字节、双字节的字、512字节的数据块(默认值)、KB、MB或GB为计数单位。

-type c  选择指定类型的文件。文件类型可以是f(普通文件)、d(目录)、b(块特殊文件)、c(字符特殊文件)、p(管道文件)、l(符号链接文件)或s(套接字文件)等。

-uid [+]n  选择匹配指定用户ID的文件。

-user uname  选择匹配指定用户的文件。指定的用户可以是一个注册用户名,也可以是用户ID号。

-writable  选择可写的文件。这个测试的主要目的是要充分考虑访问控制表以及“-perm”测试忽略的其他访问权限。

动作

-delete  删除选择的文件。如果删除成功,返回真。如果删除失败,输出错误信息,同时返回非零结束状态。注意,“-delete”会自动启用“-depth”选项,故使用时应审慎。警告:不要忘记find命令行中的动作也是按表达式计算的,如果把“-delete”动作放在表达式的第一位,将会导致find命令尝试从指定目录开始删除其中的所有文件而非经由其他表达式选项和测试条件选出的文件。因此,如果存在,一定要把“-delete”动作放在整个表达式的最后位置。

-exec cmd {} [\];  执行指定的命令。使用find命令的检索结果替换花括号,作为文件参数提交给指定的命令。对于每一个文件,在检索的起始目录处执行一次指定的命令。必要时,可在分号的前面加一个转义符号“\”。

-exec cmd {} +  执行指定的命令。使用find命令的检索结果替换花括号,作为文件参数提交给指定的命令做进一步处理。与前一个动作不同的是,这里是把find命令的检索结果汇总为一个参数集合,一次性地提交给指定的命令。因此,这个动作能够提高命令运行的性能。同样,指定的命令也是在检索的起始目录处执行的。

-execdir cmd {} [\];

-execdir cmd {} +  类似于相应的“-exec”动作,但指定的命令是在包含匹配文件的子目录(而非起始检索目录)中执行的。这种处理方法相对比较安全。如同“-exec”动作,后者(+)使用一个命令行处理多个匹配的文件(位于同一子目录)。

-fls file  类似于“-ls”,只是把输出结果写入指定的文件。

-fprint file  把选择的结果逐行写入指定的文件,每个文件路径名之后附加一个换行符。如果文件不存在,则创建命名的文件。如果文件已经存在,将会覆盖原有的文件。/dev/stdout和/dev/stderr是两个可以选用的特殊文件,分别对应标准输出和标准错误输出。

-fprint0 file  类似于“-print0”,只是把选择结果依次写入指定的文件(每个文件路径名之后附加一个NULL终止符),中间没有换行。

-fprintf file format  按照指定的格式,把选择结果写入指定的文件。有关格式的说明,详见“-fprintf”动作。注意,即使选择的结果为空,“-fprintf”也会创建指定的 文件。

-ls  以“ls -dils”命令的输出形式显示匹配检索条件的文件及其属性信息,其中包括文件的信息节点号、1KB数据块计数的文件大小、访问权限、硬链接计数、文件属主、用户组、以字节计数的文件大小、文件的修改时间及文件名等。如果查询的文件是特殊文件,文件大小字段给出的是主次设备号。

-ok cmd {}\;  其功能类似于“-exec”选项,但在执行指定的命令前需要提请用户确认。在用户输入“y”(或“Y”)之后才能继续执行,否则返回。

-okdir cmd {}\;  类似于“-execdir”动作,但在执行指定的命令前需要提请用户确认。在用户输入“y”(或“Y”)之后才能继续执行,否则返回假。在命令运行期间,其标准输入改向到/dev/null。

-print  显示选择的结果,即逐行输出符合检索条件的每个文件(文件路径名之后附加一个换行符)。这个选项是find命令默认的处理动作,可以省略。

-print0  显示选择结果,依次输出符合检索条件的每个文件(文件路径名之后附加一个NULL终止符),中间没有换行。这种输出方式使得部分处理find命令输出的程序能够正确解释包含换行符或空白字符的文件名(参见xargs命令的“-0”选项)。

-printf format  按照指定的格式,把选择结果写到标准输出。“-printf”能够解释“\n”和“\t”等常规的转义字符,还能解释“% c”形式的转换指令。如同C语言的printf函数一样,也可以在“%”与“c”之间插入表示字段宽度和精度的数字。此外,在数字前加一个减号“-”意味着左对齐,默认为右对齐。与“-print”不同,除非在指定的格式中明确增加了“\n”转义字符,“-printf”不会在输出的任何数据后面附加换行字符。下面是“-printf”支持的部分常用的转换指令:

%a  文件的最近访问时间(或选用“%Ac”)。
%Ax  文件的最近访问时间,其中x可以是一个表示日期与时间的字符,如c表示本地语言环境的日期与时间。
%c  文件信息节点的最近状态改变时间(或选用“%Cc”)。
%Cx  文件信息节点的最近状态改变时间,其中x可以是一个表示日期与时间的字符,如c表示本地语言环境的日期与时间。
%i  文件的信息节点号(十进制数值)。
%k  文件占用的磁盘空间数量(按1KB的数据块计算)。
%m  以八进制数值表示的文件模式字段,包括访问权限。如果想在数值前面增加一个前置0,可以改用“%#m”。
%n  文件的硬链接计数。
%p  文件的路径名。
%s  文件以字节为单位的大小。
%t  文件的最近修改时间(或选用“%Tc”)。
%Tx  文件的最近修改时间,其中x可以是一个表示日期与时间的字符,如
c表示本地语言环境的日期与时间。
%u  文件属主的用户名或用户ID。

-prune  如果表达式指定的名字(或模式)是一个目录,则跳过其中的任何文件,转而考察其他符合检索条件的文件。如果指定了“-depth”,则“-prune”不起作用。由于“-delete”蕴含着“-depth”,故“-prune”也不能与“-delete”一起使用。若想忽略某个目录,禁止检索其中的任何文件,可以使用“-prune”。例如,若想跳过当前目录下的“src”子目录及其中的任何文件,显示其他符合检索条件的文件,可以使用“find . -path ./src -prune -o -print”命令。

逻辑运算符

在find命令中,表达式可以做逻辑运算。下面按逻辑运算符从高到低的优先计算顺序依次列出表达式的逻辑运算形式:

( expr )  圆括号中的表达式是一个整体,具有最高的计算优先权,圆括号内所有表达式的最终计算结果为整个表达式的结果(由于圆括号是Shell特殊字符,每个括号前须加转义符号“\”)。

! expr  仅当表达式为假时,最终运算结果才能满足测试条件(感叹号通常也需要加转义符号“\”予以保护)。

expr1 expr2  两个并列的表达式(中间加空格分隔符)表示一种逻辑与的运算关系,中间蕴含着一个逻辑与运算符“-a”,见下面的说明。

expr1 [-a] expr2  仅当两个表达式均为真时,最终运算结果就能满足测试条件。当同时指定两个或多个表达式时,逻辑与是隐含的运算,故中间的运算符“-a”可以省略。

expr1 -o expr2  两个表达式的逻辑或,只要一个表达式为真,最终运算结果就能满足测试条件。

expr1 , expr2  两个并列表达式(中间加逗号分隔符)表示一种递进的运算关系。两个表达式都需要计算,最终的运算结果是第二个表达式的值(扔掉第一个表达式的值)。

应用实例

1. 从/home目录开始,检索并删除其中的所有core文件。

# find /home -name core -type f -exec /bin/rm '{}' \;

2. 从根目录开始,检索系统中设置了setuid的文件,把检索结果放在/root/suidfile文件中。

# find / -perm -4000 -fprintf /root/suidfile "%#m %u %p\n"

3. 从根目录开始,检索系统中文件容量大于100MB的所有文件,把检索结果放在/root/bigfile文件中。

# find / -size +100M -fprintf /root/bigfile "%10s %p\n"

4. 检索/data目录中最近7天内修改过的文件。

$ find /data -mtime -7

5. 检索当前目录中文件属主及其所属用户组可写的文件,可以使用下列命令之一。

$ find . -perm -220
$ find . -perm -g+w,u+w

6. 递归地显示当前目录中的所有文件,但跳过security目录中的内容,仅仅显示目录名而已。

$ find . -print -name security -prune

索引:A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z