首页 > 代码库 > linux 搜索工具

linux 搜索工具

  大家好!本文为大家介绍linux 的搜索工具:locate、find,更精确的查找工具。之前我们学过ls |grep   也能达到搜索文件的功能,但ls是基于文件名的查找,虽然搭配grep能按照一定的条件去查找文件,又因为每个文件的格式不唯一,所以这种方法也不总适用。
 
下面为大家介绍简单精确的查找工具
 
1、locate: 基于数据库的查询,非实时性,对新创建的文件需要更新数据库。local是基于文件全路径的模糊查询,查询时会判断权限
   格式:locate KEYWORD
          -i 忽略大小写
          -n X 只列举前N个匹配的项目
          updatedb 更新locate数据库 /var/lib/mlocate/mlocate.db
          -r 支持正则
 
    eg: locate conf   搜索名称或路径中带有“conf ”的文件
       locate -r ‘\.conf$’  使用Regex 来搜索以“.conf
 
2、find : 实时查询,速度肯定没locate快。但它可以基于文件大小、属主、属组、访问时间、文件名、文件类型、硬链接等更精确的查找方式。查找时也需要具有相应权限(rx)
 
  (1)语法: find [OPTION]... [ 查找路径] [ 查找条件] [ 处理动作]
    查找路径:指定具体目标路径;默认为当前目录
    查找条件:指定的查找标准,可以文件名、大小、类型、
    权限等标准进行;默认为找出指定路径下的所有文件
    处理动作:对符合条件的文件做操作,默认输出至屏幕
 
  (2)find
    -maxdepth level 最大搜索深度
    -minxdepth level 最小搜索深度
    -name 基于名称的精确查找,支持通配符*, ?, [], [^]
      eg:find -name “my*” 搜索当前目录(含子目录)中,所有文件名以my开头的文件
    -iname 基于名称忽略大小写的精确查找查找
    -empty : 空的档案-gid n or -group name : gid 是 n 或是 group 名称是 name
     -ipath p, -path p : 匹配一个路径名,ipath 会忽略大小写
    -inum 基于inode查找
    -samefile "文件名" 基于相同inode号的查找(查找硬链接)
    -links n 硬链接数为n的文件
    -regex “PATTERN”支持正则 默认为(emacs标准),匹配全路径,而不只是文件名
      eg:find -regex ".*f[1-9]" 因为匹配的是全路径所以".*"要加到前面
    -regextype egrep -regex 支持egrep同标准的正则
    -user 用户名 基于文件owner的查找
    -group 组名 基于文件group的查找
    -uid userid 基于文件uid的查找
    -gid groupid 基于文件gid的查找
    -nouser 查找没有owner的文件
    -nogroup 查找没有group的文件
    -type 基于文件类型的查找
        ? f: 普通文件
        ? d: 目录文件
        ? l: 符号链接文件
        ? s:套接字文件
        ? b: 块设备文件
        ? c: 字符设备文件
        ? p: 管道文件
 
  (3)组合条件:-a与 、-o或 、-not=! 非
        德摩根定律:
!A -a !B = !(A -o B)
!A -o !B = !(A -a B)
eg: find /tmp \( -not -user root -a -not -name ‘f*‘ \) -ls
find /tmp -not \( -user root -o -name ‘f*‘ \) –ls
需要注意的是f*表示文件名要以f开头
*f*表示只要文件名包含f即可
\(代表一个复杂表达式的开始
\)代表一个复杂表达式的结束
 
  (4)排除目录
find [-path ..] [expression] 在路径列表的后面的是表达式
  -path "/usr/sam" -prune -o -print 是 -path "/usr/sam" -a -prune -o -print 的简写表达式按顺序求值, -a 和 -o 都是短路求值,与 shell 的 && 和 || 类似如果 -path "/usr/sam" 为真,则求值 -prune , -prune 返回真,与逻辑表达式为真;否则不求值 -prune,与逻辑表达式为假。如果 -path "/usr/sam" -a -prune 为假,则求值 -print ,-print返回真,或逻辑表达式为真;否则不求值 -print,或逻辑表达式为真。
 
    eg:find /etc -path ‘/etc/sane.d‘ -a -prune -o -name "*.conf"   
      在/etc目录下查找文件名以.conf结尾的文件(除/etc/sane.d目录不查询)
      find /etc \( -path ‘/etc/sane.d‘ -o -path ‘/etc/fonts‘ \) -a -prune -o -name "*.conf"   
      在/etc目录下查找文件名以.conf结尾的文件(除/etc/sane.d目录、/etc/fonts不查询)
 
  (5)基于文件大小查找
-size [+|-]#UNIT 根据文件大小来查找
常用单位:k, M, G,c(byte)
#UNIT: (#-1, #]如:6k 表示(5k,6k]
-#UNIT:[0,#-1]如:-6k 表示[0,5k]
+#UNIT:(#,∞)如:+6k 表示(6k,∞)
find 中要想使用正规正则表达式,需要用选项 -regex "pattern",
注意 find 的常用选项 -name 是不支持正则表达式的,充其量只能说 -name 选项支持通配符 * ? []
 
 
 
  (6)基于时间戳查找
以“天”为单位;
-atime [+|-]#,
#: [#,#+1)
+#: [#+1,∞]
-#: [0,#)
-mtime
-ctime
以“分钟”为单位:
-amin
-mmin
-cmin
 
(7)基于权限查找
-perm [ mode|+mode|-mode]
mode:精确权限匹配
+mode[/mode] 任何一类(u,g,o)对象的权限中只要能一位匹配即可,或关系,+ 从centos7开始淘汰
-mode 每一类对象都必须同时拥有指定权限,与关系0 表示不关注
 
  (8)处理动作:
-print 默认
-delete 直接删除所查找到的文件,不询问。
-ls 长列出所查找到的文件
-fls file 将查找到的文件长列出导入到指定文件。
> file
-ok command {} \; 对查找到的每个文件当做下一命令的参数去执行(交互式)
-exec command {} \; 对查找到的每个文件当做下一命令的参数去执行(非交互式)
{}: 用于引用查找到的文件名称自身
 
 
 
那些天走过的弯路
 
  问题描述:
       find  -name "f2" -o -name "f3" -a -exec echo {} \;
        只会把最后一个查找条件匹配的结果传递给exec后的命令做参数
       find  \( -name "f2" -o -name "f3" \) -a -exec echo {} \;
        会把括号里所有的查询结果,作为参数传递给exec后的命令做参数
 
  困扰:
         find的查询顺序不应该是顺序执行么?当 f2 没匹配到返回false值,再去匹配第二个条件f3。
     那么应该只要匹配到一个条件返回一个true,就会通过-exec传递给命令了吧?
       经过反复调试,发现find  -name "f2" -o -name "f3" -a -exec echo {} \;  
     这种写法只会把-exec前的条件匹配到的结果传递给后面的命令,而与find的查询顺序毫无关系
 
  原理剖析:
       find -name "f2" -o -name "f3" -exec echo {} \;
       (1)不加括号会把-name "f3" -a -exec echo {} \;看成一个整体
       (2)-exec 会把结果传递给命令,不会再显示在标准输出(相当于输出重定向)
 
 
    总结:
       find把条件看成了两个部分: -name "f2" 或者 -name "f3" -exec echo {}
       (1)先来说f3,匹配到以后会把查询结果传递给exec后的命令,然后执行
          (2)-name "f2" 的查询结果,原本应该在标准输出显示出来,但因为把结果传递给了-exec,
          而exec又只传递f3的匹配结果,所以f2没有显示出来
 
 
 
练习:
1、查找/var目录下属主为root,且属组为mail的所有文件
    find /var -user root -a -group mail -ls
2、查找/var目录下不属于root、lp、gdm的所有文件
    find /var -not \( -user root -o -user lp -o -user gdm \) -ls
3、查找/var目录下最近一周内其内容修改过,同时属主不为root,也不是postfix的文件
    find /var/ -mtime -7 -not -user root -not -user postfix -ls
4、查找当前系统上没有属主或属组,且最近一个周内曾被访问过的文件
    find / -nouser -o -nogroup -a -atime -7 -ls
5、查找/etc目录下大于1M且类型为普通文件的所有文件
    find /etc/ -size +1M -a -type f -ls
6、查找/etc目录下所有用户都没有写权限的文件
    find /etc ! -perm /222 -ls
7、查找/etc目录下至少有一类用户没有执行权限的文件
    find /etc ! -perm -111 -ls
8、查找/etc/init.d目录下,所有用户都有执行权限,且其它
用户有写权限的文件
    find /etc/init.d/ -perm -113 -ls
9、查找名字符合正则表达式的文件,注意前面的‘.*’(查找到的文件带有目录)
    find ./ -regex .*so.*\.gz
 
10、查找目录并列出目录下的文件(为找到的每一个目录单独执行ls命令,没有选项-print时文件列表前一行不会显示目录名称)
    find ./ -type d -print -exec ls {} \;
 
11、查找目录并列出目录下的文件(为找到的每一个目录单独执行ls命令,执行命令前需要确认)
    find ./ -type d -ok ls {} \;

linux 搜索工具