文件查找工具locate和find的使用分析


不管是在windows系统中还是在Linux系统中,我们经常会一些文件进行搜索查找,而在Linux系统中经常用到的搜索工具有locate和find,这两种搜索工具的工具原理和用法都不相同,一下将这对这两种搜索工具的使用进行分析。

1、locate工具的工作原理是对/var/lib/mlocate/mlocat.db数据库进行文件搜索,而不是实时的在磁盘上搜索,因此它具有查找速度快的特点。mlocat.db数据库中包含所有本地文件信息,使用locate进行文件查找时主要依赖于其事先构建好的索引,其索引的构建是在系统较为空闲时周期性的自动进行,并且索引的构建过程需要遍历整个根文件系统,因此构建索引时的资源消耗比较大,由此可以发现locate还具有查找到的文件都是非实时文件的特点,也就是说locate查不到最近新变动过的文件,想要查找最新变动过的文件需要先使用updatedb命令手动更新数据库。locate还具有模糊查找的特点,可以理解为locate命令后面跟的不是文件名,而是关键字,关键字也可以使用文件通配符表示,只要符合关键字内容的文件都能被查找出来,另外locate搜索的不仅仅是文件名,而是全路径。

locate的用法:locate [OPTION]... [PATTERN]...

locate常用选项如下:

-i:忽略大小写

-n:只列出搜索到的前几行内容

-r:支持使用正则表达式


2、find工具的工作原理与locate不同,find是实时的针对磁盘进行文件搜索的,并且find是可以对指定目录进行精确查找的,因此find相对于locate来说查找速度较慢。find的功能非常强大,并且使用灵活。

find的用法:find [OPTION]... [查找路径] [查找条件] [处理动作]

查找路径:查找指定目录下的所有文件,默认递归查找,如指定查找用户家目录下的所有文件

查找条件:根据指定的条件进行文件查找,如根据日期查找、根据文件名进行精确查找、或根据文件所属用户进行查找等。

处理动作:是指将查找到的文件进行怎样的处理,如复制、删除等,默认是-print,即列出查找到的所有文件


下面将对find工具的具体使用进行分析:


  • 查找路径

根据指定的路径进行文件查找,如果不指定路径,默认情况下查找当前路径下的所有文件

[root@liang ~]# find     或     [root@liang ~]# find ./   #两个命令的意思是一样的,都是查找当前目录下的所有文件

[root@liang ~]# find /etc/      #查找/etc/目录下的所有文件

注意:如果指定的目录是软链接,则指定该目录时一定要在后面加上斜线,否则查找的是文件而不是目录下的文件

[root@liang /]# ll /etc/init.d
lrwxrwxrwx. 1 root root 11 6月  15 16:47 /etc/init.d -> rc.d/init.d
[root@liang /]# find /etc/init.d 
/etc/init.d
[root@liang /]# find /etc/init.d/
/etc/init.d/
/etc/init.d/rpcidmapd
...
  • 查找条件

find命令的强大之处在于其查找条件有很多,可以根据不同的条件查找所需要的文件,并且使用非常灵活,下面将一一介绍不同的查找条件:

-name FILENAME:根据文件名精确查找文件,可以使用文件通配符

#查找当前目录下sshd文件
[root@liang testdir]# find -name sshd 
#查找/etc 目录下的passwd文件
[root@liang testdir]# find /etc -name passwd

-iname FILENAME:根据文件名精确查找文件,可以使用文件通配符,与-name不同的是不区分字母大小写-

-inum NUM:按磁盘上存储文件的inode号查找

[root@liang testdir]# find -inum 2490447

-samefile FILENAME:查找存储在磁盘上相同inode号的文件

#查找当前目录下与acpid相同inode号的文件
[root@liang testdir]# find -samefile acpid

-links NUM:查找软链接的链接数为NUM个的文件

#查找当前目录下连接数为10的所有文件
[root@fengl /]# find -links 10

-regex “PATTERN”:使用正则表达式查找,PATTERN匹配的是整个文件路径字符串,而不仅仅是文件名

#查找当前目录下所有以a或b开头的文件,注意正则表达式一定是匹配全路径的,当前目录下应加上“./”
[root@liang testdir]# find -regex \./[ab].*

-user USERNAME:查找属主为指定用户(UID)的文件。

-uid UserID:根据用户UID进行查找

-group GROUPNAME:查找属组为指定组(GID)的文件

-gid GroupID:根据组的GID进行查找

-user与-uid其实都是根据用户UID进行文件查找的,如果两个用户的UID一样,则根据一个用户的用户名查找文件时会将其属主的文件都列出来,同理,-group和-gid也是一样的,其实都是根据组的GID进行文件查找的

#根据用户查找
[root@liang testdir]# find /home -user ggg -ls
1703938    4 drwx------   3 liang    liang        4096 8月  3 05:29 /home/liang
1703939    4 -rw-r--r--   1 liang    liang         124 5月 11 07:21 /home/liang/.bashrc
1703940    4 drwxr-xr-x   2 liang    liang        4096 11月 12  2010 /home/liang/.gnome2
1703995    4 -rw-------   1 liang    liang         297 8月  3 05:29 /home/liang/.bash_history
1703941    4 -rw-r--r--   1 liang    liang         176 5月 11 07:21 /home/liang/.bash_profile
1703942    4 -rw-r--r--   1 liang    liang          18 5月 11 07:21 /home/liang/.bash_logout
1704026    4 drwx------   3 liang    ggg          4096 8月 17 00:50 /home/ggg
1704027    4 -rw-r--r--   1 liang    ggg           124 5月 11 07:21 /home/ggg/.bashrc
1704028    4 drwxr-xr-x   2 liang    ggg          4096 11月 12  2010 /home/ggg/.gnome2
1704029    4 -rw-r--r--   1 liang    ggg           176 5月 11 07:21 /home/ggg/.bash_profile
1704030    4 -rw-r--r--   1 liang    ggg            18 5月 11 07:21 /home/ggg/.bash_logout
#根据UID查找
[root@liang testdir]# find /home -uid 500 -ls 
1703938    4 drwx------   3 liang    liang        4096 8月  3 05:29 /home/liang
1703939    4 -rw-r--r--   1 liang    liang         124 5月 11 07:21 /home/liang/.bashrc
1703940    4 drwxr-xr-x   2 liang    liang        4096 11月 12  2010 /home/liang/.gnome2
1703995    4 -rw-------   1 liang    liang         297 8月  3 05:29 /home/liang/.bash_history
1703941    4 -rw-r--r--   1 liang    liang         176 5月 11 07:21 /home/liang/.bash_profile
1703942    4 -rw-r--r--   1 liang    liang          18 5月 11 07:21 /home/liang/.bash_logout
1704026    4 drwx------   3 liang    ggg          4096 8月 17 00:50 /home/ggg
1704027    4 -rw-r--r--   1 liang    ggg           124 5月 11 07:21 /home/ggg/.bashrc
1704028    4 drwxr-xr-x   2 liang    ggg          4096 11月 12  2010 /home/ggg/.gnome2
1704029    4 -rw-r--r--   1 liang    ggg           176 5月 11 07:21 /home/ggg/.bash_profile
1704030    4 -rw-r--r--   1 liang    ggg            18 5月 11 07:21 /home/ggg/.bash_logout
#根据用户组名查找
[root@liang testdir]# find /home -group feng -ls 
1703943    4 drwx------   3 feng     feng         4096 8月  3 02:16 /home/feng
1703944    4 -rw-r--r--   1 feng     feng          124 5月 11 07:21 /home/feng/.bashrc
1703945    4 drwxr-xr-x   2 feng     feng         4096 11月 12  2010 /home/feng/.gnome2
1703946    4 -rw-r--r--   1 feng     feng          176 5月 11 07:21 /home/feng/.bash_profile
1703947    4 -rw-r--r--   1 feng     feng           18 5月 11 07:21 /home/feng/.bash_logout
#根据用户组的GID查找
[root@liang testdir]# find /home -gid 501 -ls 
1703943    4 drwx------   3 feng     feng         4096 8月  3 02:16 /home/feng
1703944    4 -rw-r--r--   1 feng     feng          124 5月 11 07:21 /home/feng/.bashrc
1703945    4 drwxr-xr-x   2 feng     feng         4096 11月 12  2010 /home/feng/.gnome2
1703946    4 -rw-r--r--   1 feng     feng          176 5月 11 07:21 /home/feng/.bash_profile
1703947    4 -rw-r--r--   1 feng     feng           18 5月 11 07:21 /home/feng/.bash_logout

-nouser:查找没有属主的文件

-nogroup:查找没有属组的文件

#查找/home/目录下没有属组的所有文件
[root@liang liang]# find /home -nogroup -ls
1704026    4 drwx------   3 ggg      4334         4096 8月 17 00:50 /home/ggg
1704027    4 -rw-r--r--   1 ggg      4334          124 5月 11 07:21 /home/ggg/.bashrc
1704028    4 drwxr-xr-x   2 ggg      4334         4096 11月 12  2010 /home/ggg/.gnome2
1704029    4 -rw-r--r--   1 ggg      4334          176 5月 11 07:21 /home/ggg/.bash_profile
1704030    4 -rw-r--r--   1 ggg      4334           18 5月 11 07:21 /home/ggg/.bash_logout
#查找/home/目录下没有属主的所有文件
[root@liang liang]# find /home -nouser -ls
2097156    4 drwx------   3 4321     root         4096 8月  3 04:10 /home/test
2097157    4 -rw-r--r--   1 4321     root          124 5月 11 07:21 /home/test/.bashrc
2097158    4 drwxr-xr-x   2 4321     root         4096 11月 12  2010 /home/test/.gnome2
2097159    4 -rw-r--r--   1 4321     root          176 5月 11 07:21 /home/test/.bash_profile
2097160    4 -rw-r--r--   1 4321     root           18 5月 11 07:21 /home/test/.bash_logout

-type TYPE:根据文件类型进行查找,文件类型包括以下几种:

f:普通文件

d:目录文件

l:符号链接文件

s:套接字文件

b:块设备文件

c:字符设备文件

p:管道文件

#查找/home目录下的所有普通文件
[root@liang liang]# find /home -type f
#查找/home目录下的所有目录文件
[root@liang liang]# find /home -type d

-size [+|-]#UNIT:“#”代表数字,按照文件大小来查找,UNIT代表单位,常用单位有k、M、G

#UNIT表示的范围是:(#-1,#]

-#UNIT表示的范围是:[0,#-1]

+#UNIT表示的范围是:(#,∞)

#查找/usr目录下大小为10M的文件,其实查到的是9-10M之间的文件
[root@liang liang]# find /usr -size 10M
#查找/usr目录下大于10M的文件
[root@liang liang]# find /usr -size +10M
#查找/usr目录下小于等于10M的文件
[root@liang liang]# find /usr -size -11M

以下“#”表示数字

-atime [+|-]#:根据访问时间戳查找,以“天”为单位

-amin [+|-]#:根据访问时间戳查找,以“分钟”为单位

-mtime [+|-]#:根据修改时间戳查找,以“天”为单位

-mmin [+|-]#:根据修改时间戳查找,以“分钟”为单位

-ctime [+|-]#:根据状态变更时间戳查找,以“天”为单位

-cmin [+|-]#:根据状态变更时间戳查找,以“分钟”为单位

#表示的范围是:[#,#-1)

-#表示的范围是:[0,#)

+#表示的范围是:[#+1,∞]

#查找/home目录下前3分钟时访问的文件,实际查找的是前2-3分钟之间访问的文件
[root@liang liang]# find /home -amin 3 
#查找/home目录下3分钟内访问的文件
[root@liang liang]# find /home -amin -3
#查找/home目录下3分钟前访问的文件
[root@liang liang]# find /home -amin +2

-perm  MODE:根据权限进行文件查找,精确匹配权限

-perm -MODE:根据权限进行文件查找,每一类(u,g,o)对象都必须同时拥有指定的权限,“与”关系。如-222表示对应的u、g、o三者都有写权限的文件。0表示不关注,如-220表示对应的u、g两者都有写权限的文件。

-perm /MODE:centos7之前的版本还可以用-perm +MODE表示,也是根据权限进行文件查找,任何一类(u,g,o)对象中只要有一位匹配即可,或关系。如/222表示对应的u,g,o三者中任何一个有写权限的文件。

#查找/etc/目录下权限为644的所有文件
[root@liang liang]# find /etc/ -perm 644
#查找/etc/目录下任何一类用户有执行权限的所有文件
[root@liang liang]# find /etc/ -perm /111
#查找/etc/目录下所有用户都有执行权限的所有文件
[root@liang liang]# find /etc/ -perm -111 
#查找/etc/目录下其他用户有执行权限的所有文件
[root@liang liang]# find /etc/ -perm -001
  • 处理动作

-print:find命令默认的处理动作,将查找到的文件显示至屏幕上

-ls:类似与对查找到的文件执行“ls -l”命令

#查找当前目录下名为network的文件,使用默认动作处理查找到的文件
[root@liang7 etc]# find -name network
./sysconfig/network
./rc.d/init.d/network
./vmware-tools/scripts/vmware/network
#查找当前目录下名为network的文件,使用-print选项处理查找到的问及那
[root@liang7 etc]# find -name network -print
./sysconfig/network
./rc.d/init.d/network
./vmware-tools/scripts/vmware/network
#查找当前目录下名为network的文件,使用-ls选项处理查找到的文件
[root@liang7 etc]# find -name network -ls
137432923    4 -rw-r--r--   1 root     root           22 Jul 21 02:52 ./sysconfig/network
939715    8 -rwxr-xr-x   1 root     root         6630 Sep 16  2015 ./rc.d/init.d/network
269689071   16 -rwxr-xr-x   1 root     root        14638 Nov 21  2015 ./vmware-tools/scripts/vmware/network

-delete:删除查找到的文件全部删除(此选项不做演示)

-fls file:将查找到的所有文件的长格式信息保存至指定文件中

#查找当前目录下名为network的文件,使用-fls选项将查找到的文件的长格式结果保存在find.log文件中
[root@liang7 etc]# find -name network -fls find.log
#查看保存到find.log文件中的结果
[root@liang7 etc]# cat find.log 
137432923    4 -rw-r--r--   1 root     root           22 Jul 21 02:52 ./sysconfig/network
939715    8 -rwxr-xr-x   1 root     root         6630 Sep 16  2015 ./rc.d/init.d/network
269689071   16 -rwxr-xr-x   1 root     root        14638 Nov 21  2015 ./vmware-tools/scripts/vmware/network

-ok CMMAND {} \;:对查找到的每个文件执行由COMMAND指定的命令,并且对于每个文件执行命令前都会交互式的要求用户确认

-exec CMMAND {} \;:对查找到的每个文件执行由COMMAND指定的命令,与-ok不同的是没有交互式提醒,直接进行CMMAND的操作,不需要用户确认

#使用-exec选项进行备份,要求以“.orig”作为扩展名备份当前目录下以“.conf”结尾的配置文件
[root@liang7 testdir]# find -name "*\.conf" -exec cp {} {}.orig \;
#查看备份后的文件
[root@liang7 testdir]# find -name "*.orig"
./fonts/conf.d/66-sil-abyssinica.conf.orig
./fonts/conf.d/59-liberation-mono.conf.orig
./fonts/conf.d/65-0-lohit-tamil.conf.orig
...
#提示修改当前目录下其他用户具有写权限的普通文件
[root@liang7 testdir]# find -type f -perm -002 -ok chmod o-w {} \;
< chmod ... ./yum.conf > ? y
#查看修改权限后的文件
[root@liang7 testdir]# find -name yum.conf -ls
   774    4 -rw-rw-r--   1 root     root          970 Aug 16 22:18 ./yum.conf

以上命令中用到的“{}”的作用是引用find查找到的文件名称自身,但是有时候查找到的文件有很多,将会超出后面命令的参数范围,这时后面的命令执行时将会提示错误,这种情况下可以使用xargs命令规避此问题。

find | xargs CMMAND

#查找当前目录下所有以“.orig”结尾的文件并删除
[root@liang7 testdir]# find -name "*.orig" | xargs rm
#查看删除结果
[root@liang7 testdir]# find -name "*.orig" | wc -l
0


  • 查找条件之间的逻辑关系

find命令可以同时跟多个查找条件,默认情况下多个查找条件之间的关系是“与”关系。多个查找条件之间的关系有如下几种:

-a:“与”关系,比如查找/etc目录下属主为test用户并且具有执行权限的文件,这时两多个查找条件之间需要使用-a选项,默认情况下就是-a;

#默认情况下的写法
[root@liang7 testdir]# find /etc -user test -perm /100
#使用-a选项的写法
[root@liang7 testdir]# find /etc -user test -a -perm /100

-o:“或”关系,比如查找当前目录下以 “.sh”结尾的文件或查找以“.conf”f结尾的文件,这时两个查找条件之间需要使用-o选项;

#使用-o选项的写法
[root@liang7 testdir]# find -name "*.sh" -o -name "*.conf"

-not或 !:“非”选项,比如查找当前目录下除了test用户外的所有文件,这时指定用户的条件参数前需要使用-not选项;

#使用-not选项的写法
[root@liang7 testdir]# find -not -user test
#使用!的写法
[root@liang7 testdir]# find ! -user test

-a,-o,-not三个选项同时使用时,也是有优先级之分的。

-a的优先级要高于-o的优先级,如果查找条件中同时出现-a和-o选项,则先执行-a后执行-o,如:A  -o B  C,其执行的结果是满足条件A或满足条件BC,如果想实现满足条件A或B,且满足条件C,需要使用小括号将A或B括起来,如(A -o B) C 。

#查找当前系统上没有属主或属组,且最近一周没有被访问过的文件
[root@liang7 testdir]# find / \( -nouser -o -nogroup \) -atime -7

当使用-not选项且将多个查找条件用小括号括起来是需要注意德·摩根定律,该定律的表示方法如下:

(非P)或(非Q)=非(P 且 Q)即(! P)-o (! Q)=! (P -a Q)

(非P)且(非Q)=非(P 或 Q)即(! P)-a (! Q)=! (P -o Q)

#查找/var目录下不属于root、lp、gdm的所有文件(带有小括号的写法)
[root@liang7 testdir]# find /var -not \( -user root -o -user lp -o -user gdm \)
#查找/var目录下不属于root、lp、gdm的所有文件(不使用小括号的写法)
[root@liang7 testdir]# find /var -not -user root -not -user lp -not -user gdm 
#查找/var目录下最近一周内其内容修改过,同时属主不为root,也不是postfix的文件(带有小括号的写法)
[root@liang7 testdir]# find /var -mtime -7 -not \( -user root -o -user postfix \)
#查找/var目录下最近一周内其内容修改过,同时属主不为root,也不是postfix的文件(不使用小括号的写法)
[root@liang7 testdir]# find /var -mtime -7 -not -user root -not -user postfix