文章目录
- 一、locate--较简单的方式查找文件
- 二、find--较复杂的方式查找文件
- 2.1、test选项
- 2.2、action选项
- 2.3、返回到playground文件夹
- 2.4、option选项
一、locate–较简单的方式查找文件
locate
命令通过快速搜索数据库,以寻找路径名与给定的子字符串相匹配的文件,同时输出所有匹配结果。例如,假定查找名称以zip字符串开头的程序,由于查找的是程序文件,所以可以认为包含所要查找的程序的路径名应以bin/结尾。
因此,可以尝试下面的命令行。
locate
程序将搜索该路径名数据库,并输出文件名包含字符串bin/zip的所有文件。
有时搜索需求并不是这么简单,这时便可以用locate
命令结合其他诸如grep
这样的工具实现一些更有趣的搜索。
locate
程序已经使用了很长时间,因此出现了多种衍生体。slocate
和mlocate
是现代Linux发行版本中最常见的两个衍生体,而它们通常都是由名为locate的符号链接访问的。不同版本的locate
有一些相同的选项设置,而有些版本则包括正则表达式匹配和通配符支持等。我们可以查看locate
的man
手册页确定系统安装的是哪个版本的locate
。
二、find–较复杂的方式查找文件
locate
程序查找文件仅仅是依据文件名,而find
程序则是依据文件的各种属性在既定的目录(及其子目录)里查找。
find
最简单的用法就算用户给定一个或是更多个目录名作为其搜索范围。下面就用find
命令列出当前系统主目录(~)下的文件列表清单。
对于一些比较活跃的用户,一般系统内文件会比较多,使得上诉命令行输出的列表肯定很长。不过,列表信息是以标准形式输出的,所以可以直接将此输出结果作为其他程序的输入。如下就是用wc
程序计算find
命令搜索到的文件的总量。
find
命令的美妙之处就是可以用来搜索符合特定要求的文件,它通过综合应用test选项、action选项以及option选项实现高级文件搜索。
2.1、test选项
假定我们想要查找的是目录文件,我们可以添加下面的test选项达到此目的。
添加test参数-type d
可以将搜索范围限制为目录,而下面的例子中使用-type f
则表示只对普通文件进行搜索。
find支持搜索的文件类型
文件类型 | 描述 |
b | 块设备文件 |
c | 字符设备文件 |
d | 目录 |
f | 普通文件 |
l | 符号链接 |
另外我们还可以添加其他的test选项参数实现依据文件大小和文件名的搜索。如下命令行就是用来查找所有符合*.JPG通配符格式以及大小超过1MB的普通文件。
本例中添加的-name "*.JPG"
的test选项表示查找的是符合.JPG通配符格式的文件。注意,这里将通配符扩在双引号中是为了避免shell路径名扩展。另外ia添加的-size +1M
的test选项,前面的加号表示查找的文件大小比给定的数值1M大。若字符串前面是减号则代表要比给定数值小,没有符号则表示与给定值完全相等。为末的M是计量单位MB(兆字节)的简写,下表列出了每个字母与特定计量单位之间的对应关系。
find支持的计量单位
字母 | 单位 |
b | 512字节的块(没有具体说明时的默认值) |
c | 字节 |
w | 两个字节的字 |
k | KB(每单位包含1024字节) |
M | MB(每单位包含1048576字节) |
G | GB(每单位包含1073741824字节) |
find
命令支持多种test参数,下表概括了一些常见的参数。
find命令的test参数
test参数 | 描述 |
-cmin n | 匹配n分钟前改变状态(内容或属性)的文件或目录。如果不到n分钟,就用-n,如果超过n分钟,就用+n |
-cnewer file | 匹配内容或属性的修改时间比文件file更晚的文件或目录 |
-ctime n | 匹配系统中n*24小时前文件状态被改变(内容、属性、访问权限等)的文件或目录 |
-empty | 匹配空文件及空目录 |
-group name | 匹配属于name组的文件或目录。name可以描述为组名,也可以描述为该组的ID号 |
-iname pattern | 与-name test项功能类似只是不区分大小写 |
-inum n | 匹配索引节点是n的文件,该test选项有助于查找某个特定索引节点上的所有硬件连接 |
-mmin n | 匹配n分钟前内容被修改的文件或目录 |
-mtime n | 匹配n*24小时前只有内容被更改的文件或目录 |
-name pattern | 匹配由特定通配符模式的文件或目录 |
-newer file | 匹配内容的修改时间比file文件更近的文件或目录。这在编写shell脚本进行文件备份的时候非常有用。每次创建备份时,更新某个文件(比如日志),然后用find+此参数选项来确定上一次更新后哪个文件改变了 |
-nouser | 匹配不属于有效用户的文件或目录。该test可以用来查找那些属于已删除账户的文件,也可以用来检测攻击者的活动 |
-nogroup | 匹配不属于有效组的文件或目录 |
-perm mode | 寻找访问权限与既定模式匹配的文件或目录。既定模式可以以八进制或符号的形似表示 |
-samefile name | 与-inum test选项类似。匹配与file文件用相同的inode号的文件 |
-size n | 匹配n大小的文件 |
-type | 匹配c类型的文件 |
-user name | 匹配属于name用户的文件和目录。name可以描述为用户名也可以描述为该组的ID号 |
注意:前面所讲述的“+”和“-”号的用法适用于所有用到数值参数的情况
操作符
即使拥有了find
命令提供的所有test参数,我们仍然会需要一个更好的工具来描述test参数之间的逻辑关系。例如,如果我们需要确定某目录下是否所有的文件和子目录都有安全的访问权限,该怎么办?原则上就是去查找那些访问权限不是0600的文件和访问权限不是0700的子目录。幸运的时,find
命令的test选项可以结合逻辑操作从而建立具有复杂逻辑关系的匹配条件。我们可以用下面的命令行来满足上述find
命令的匹配搜索。
find命令的逻辑操作符
操作符 | 功能描述 |
-and | 查找使该操作符两边的检验条件都是i真的匹配文件。有时直接缩写成-a。注意如果两个检测条件之间没有显示的显示操作符,and就是默认的逻辑关系 |
-or | 查找使该操作符任何一边的检测条件为真的匹配文件。有时直接缩写成-o |
-not | 查找使该操作符后面的检测条件为假的匹配文件。有时直接缩写成-! |
() | 多个检测条件和逻辑操作符一起组成更长的表达式,而()操作符就是用来区分逻辑表达式优先权的。默认的情况下,find命令从左向右运算逻辑值。然而有时为了获得想要的结果必须扰乱默认的执行顺序,即便不需要,将一串字符表达式扩起来对提高命令的可读性也很有帮助。请注意,括号字符在shell环境中有特殊意义,所以必须将它们在命令行中用引号引起来,这样此阿能作为find的参数传递,通常用反斜杠来避免这样的问题 |
2.2、action选项
前面的find
命令已经查找到所需要的文件,但是我们真正想做的是处理已查找到的文件。幸运的是,find
命令允许直接对搜索结果执行动作。
预定义动作
对搜索到的文件进行操作,既可以用诸多现成的预定义动作指令,也可以使用用户自定义的动作。首先来看一些预定义动作:
预定义的find命令操作
动作 | 功能描述 |
-delete | 删除匹配文件 |
-ls | 对匹配文件执行ls操作,以标准格式输出其文件名以及所要求的其他信息 |
-print | 将匹配的文件的全路径以标准形式输出。当没有指定任何具体操作时,该操作是默认操作 |
-quit | 一旦匹配成功便退出 |
与test参数选项相比,actions参数选项数量更多,可以参考find的man手册页获取更全面的信息。
find ~
,此命令产生了一个包含当前系统主(~)目录中所有文件和子目录的列表。该列表之所以会在屏幕上显示,是因为在没有指定其他操作的情况下,-print操作是默认的。因此,find ~
与find ~ -print
是等效的。
当然也可以使用find
命令删除满足特定条件的文件。示例如下,此命令行用于删除.BAK(这种文件一般是用来指定备份文件的)后缀的文件。
本例中,用户主目录及其子目录下的每个文件都被搜索了一遍匹配文件名以.BAK结尾的文件。一旦被找到,则直接删除。
注意:毫无疑问,使用-delete操作时一定要格外小心,最好先用-print操作确认搜索结果后再执行-delete删除命令
上述命令用来查找所有文件名以.BAK结尾的普通文件(-type f)并且以标准形式(-print)输出每个匹配文件的相关路径名。然而,该命令行之所以照这样的方式执行是由每个test选项和action选项之间的逻辑关系决定的。记住,每个test选项和action选项之间默认的逻辑关系是与(and)逻辑。下面的命令行逻辑关系能更清楚地体现这一点:
test选项与action选项之间逻辑关系决定了它们的执行情况,所以test选项和action选项的顺序很重要。例如,如果重新排列这些test选项和action选项,并将-print
操作作为逻辑运算的第一个操作数,那么命令行的运行结果将会有很大的不同。
此命令行会把每个文件显示出来(因为-print操作运算符总是为真),然后在对文件类型以及特定的文件扩展名进行匹配检查。
用户自定义操作
除了已有的预定义操作命令,同样也可以任意调用用户想要操作的操作命令。传统的方法就是像以下命令行使用-exec操作。
该格式中的command表示要执行的操作命令名,{}花括号代表的是当前路径,而分号作为必需的分隔符表示命令结束。使用-exec
完成-delete
操作示例如下:
同样,由于括号和分号字符在shell环境下有特殊含义,所以在输入命令行时,要将它们用引号引起来或者使用转义符隔开。
当然,交互式地执行用户自定义操作也不是不可能。通过使用-ok操作取代原来的-exec
操作,每一次指定命令执行之前系统都会询问用户。
上例中,查找文件名以b字符开始的文件,并且每次找到匹配文件后执行ls -l
命令。-ok
操作会在ls命令执行之前询问用户是否执行。
提高效率
当使用-exec
操作时,每次查找到匹配文件后都会调用执行一次指定命令。但有时用户更希望只调用一次命令就完成对所有文件的操作。例如,多数人可能更喜欢这样的命令执行方式。
而不是以下这样的方式:
第一种方式只需要执行命令一次,而第二种方式则要多次重复执行。实现这样的一次操作有两种方法:一种方式比较传统,使用为外部命令xargs
;另一种则是使用find
本身自带的新特性。首先介绍下第二种方法。
每次找到匹配文件后就执行一次ls
命令。将上述命令行改为下面的命令行。
我们也能得到相同的结果,但是系统整体只执行一次ls
命令
同样我们可以使用xargs
命令获得相同的效果,xargs
处理标准输入信息并将其转变为某指定命令的输入参数列表。结合前面的实例,我们可以这样使用xargs
命令。
该命令行中,find命令的执行结果直接作为xargs
输入,xargs反过来将其转换成了ls
命令的输入参数列表,最后执行ls
操作。
注意:虽然一个命令行中可允许输入的参数有很多,但这并不表示可以无限输入,也存在命令行过长而使得shell编辑器无法承受的情况。如果命令行中包含的输入参数太多而超过了系统支持的最大长度,xargs只会尽可能对最大数量的参数执行指定操作,并不断重复这一过程直到所有标准输入全部处理完毕。在xargs命令后面添加–show-limits选项,即可直到命令行最大能承受的参数数量。
2.3、返回到playground文件夹
现在可以实际应用 find
命令了。首先让我们创建一个包含很多子目录及文件的playground文件夹平台。
我们使用上述命令创建了一个包含100个子目录的playground文件夹,并且每个子目录中又包含26个空文件。
我们创造这个奇迹的方法包含了一个熟悉命令mkdir
、一个奇异的shell花括号扩展以及一个新命令touch
。mkdir
命令结合-p选项(-p选项使mkdir命令按指定的路径创建父目录)的同时用花括号扩展,便完成了100个目录的创建。
touch
命令一般用于设定或是更新文件的修改时间。然而,当文件名参数是一个不存在的文件时,那么该命令就会创建一个空文件。
playground文件夹里,总共创建了100个较多file-A的文件。现在,我们可以查找它们。
注意:与
ls
命令不同,find
命令不会产生有排列顺序的结果,其输出顺序是由在存储设备中的布局决定的。
下面来看一个根据文件的修改时间查找文件的例子,这在创建备份文件以及按时间顺序排列文件是非常有用。首先需要创建一个用作比较时间的参照文件。
该命令行创建了一个名为timestamp的空文件,并将当前时刻设为该文件的修改时间。我们可以使用另外一个便捷的命令stat
来检验执行效果,stat
命令可以说是ls
的增强版,该命令会将系统所掌握文件的所有信息及属性全部显示出来。
当我们再一次对此文件执行touch
命令并用stat
命令检验时,会发现文件的时间得到了更新。
接下来,我们便可以使用find
命令更新playground文件夹里的一些文件。
上述命令更新了playground文件夹里面叫做file-B的所有文件。下面我们通过比较参照文件timestamp与其他文件的修改时间,使用find
命令查找刚刚被更新的文件。
命令行的运行结果包含100个文件名为file-B的文件。由于我们是在对timestamp文件执行了touch
命令之后,才对playground文件夹和宗对名为file-B的所有文件执行力touch操作,所以它们现在要比timestamp文件新,从而我们可选用-newer
test选项来查找。
2.4、option选项
option选项用于控制find
命令的搜索范围。在构成find
命令的表达式时,它们可能包含在其他测试选项或行为选项之中。下表列出了最常用的option选项:
find命令的option选项
选项 | 描述 |
-depth | 引导find程序处理目录前先处理目录内文件。当指定-delete操作时,该参数选项会自动调用 |
-maxdepth levels | 当执行测试条件行为时,设置find程序陷入目录数的最大级别数 |
-mindepth levels | 当应用测试条件行为之前,设置find程序陷入目录数的最小级别数 |
-mount | 引导find不去遍历挂载在其他文件系统上的目录 |
-noleaf | 指导find程序不要基于“正在搜索类UNIX文件系统”的假设来优化它的搜索。当扫描DOS/Windows文件系统和CD时,会用到该选项 |