在这一章当中我们开始讲述文件的查找命令,在Linux中,主要围绕这两个命令,一个是locate。另一个是find命令。

一、文件查找

  我们在Windows中查找某个文件,例如(C,D,E,F)盘其中一个分区或者是整个分区来进行查找,那么查找之后,符合查找条件的文件会自动显示出来,这就是文件查找的一个过程,那么文件查找的大致解释就是:在文件系统上查找符合条件的文件,并予以显示。这个和此前学到的grep命令有所区别,grep是用来匹配字符串的,但文件查找是查找该文件的本身,而不是该文件的内容,而对于在Linux中文件查找的实现工具为:locate和find。只不过这两个命令实现的机制截然不同。

二、locate命令

  locate命令是一个模糊匹配的查找命令,只要该路径中包含查找的字符,都会予以显示,其查找速度快,性能极佳,只不过并不是遍历整个文件系统来实现的,而是查询事先构建好的数据库,这个数据库并不是实时的,等待系统空闲时,是通过某个时刻自动来构建。所以我们来总结以下该命令的主要特性:

  locate:
     依赖于事先构建好的索引库;事先如果没有,通过某个周期性任务;
        系统自动实现(周期性任务);
        手动更新数据库(updatedb);
        
    工作特性:
        查找速度快;
        模糊查找;
        非实时查找;

  locate命令的格式为:

   locate [OPTION]... PATTERN...
    -b:只匹配路径中的基名;
    -c:统计出共有多少个符合条件的文件;
    -r:BRE
    
   注意:索引构建过程需要遍历整个根文件系统,极其消耗资源;

三、find命令

  locate相对find命令而言,后者更加强大一些,它的执行过程和locate有所不同,find命令是直接通过文件系统进行实时查找遍历,并没有那种索引数据库这样的一个中间环节存在,所以并不依赖该数据库,但是文件系统的路径很多,文件数量很是庞大,所以我们可以在该命令下指定某些条件来缩小查找范围。但比起locate,性能差一些,毕竟是在文件系统内进行实时性查找,能精确反馈。所以我们来总结一下该命令的主要特性:

  find:
    实时查找工具,通过遍历指定其实路径文件系统层级结构完成文件查找;
    
    工作特性:
        查找速度:略慢;
        精确查找
        实时查找;

  find命令的格式为:

   find [OPTIONS] [查找的起始路径] [查找条件] [处理动作]

  以上都是可选的,默认为find命令时,只会在当前路径下查找,由于没有指定查找条件,所以都会符合条件,而处理的动作默认就是标准输出。

   查找其实路径:指定具体搜索目标起始路径;默认为当前目录;
   查找条件:指定的查找标准,可以根据文件名、大小、类型、从属关系、权限等等标准来进行;默认为找出指定路径下的所有文件;
   处理动作:对符合查找条件的文件做出的动作,例如删除等操作;默认为输出至标准输出(屏幕);

   默认没有指定条件时,都会符合显示;

3.1 查找条件

  查找条件也可以称作查找标准,是由一个-和长选项或可以理解为完整单词组成用作测试,符合该条件时进行默认或指定的处理,所以查找条件或查找标准也叫做其表达式,由选项和测试组成。我们主要讲的就是查找条件当中的测试的实现,而测试主要由以下类型组成:
  我们来先说第一个,根据文件名来进行查找的测试条件。

   根据文件名来查找:
    -name "pattern"
    -iname "pattern"
        支持glob风格的通配符;不是正则表达式风格;
            *, ?, [], [^]
        
    -regex pattern:基于正则表达式模式查找文件,匹配整个路径,而非基名;

  第二个就是根据其文件从属关系进行查找,这就表示看一下该文件的属主属组是那个用户。

   根据文件从属关系查找:
    -user USERNAME:查找属主指定的用户中所有的文件;
    -group GRPNAME:查找属组指定组中的所有文件;

  如果文件属主和属组没有或被删除的话,只显示UID和GID,那我们也可以通过属主属组的ID进行查找。

    -uid UID:查找属主指定的UID文件;
    -gid GID:查找属组指定组的所有文件;

  反过来,只要ID号没有属主属组的文件,我们就称之为没有属主属组的文件。

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

  那么第三个是根据文件的类型来进行查找的测试条件。

   根据文件的类型查找:
    -type TYPE:
        f:普通文件;
        d:目录文件;
        l:符号链接文件;
        b:块设备文件;
        c:字符设备文件;
        p:管道文件;
        s:套接字文件;

  我们可以编辑复杂的条件测试,只要是测试的结果通常为布尔型,要不为true要不为false,所以根据其逻辑的运算模式组合起来,而逻辑运算也无非就是我们之前所讲的与、或、非、异或组合起来,而在此处是讲查找的条件连接起来。

   组合测试:
    与:-a, 默认组合逻辑;
    或:-o
    非:-not, !

  我们继续说第四个,第四个就是根据文件大小来进行查找,默认是按照字节单位,那么带加减号时,并不是精确查找,直接默认写单位的话,它是一个半开半闭区间,相当于就是这个数字减去1并且小于等于该数字的本身,意味着可以小于这个值,但要小于等于这个单位数字的本身,不能超过该数字。
  而-#UNIT,就是小于所指定的文件单位,不能超过文件本身。
  而+#UNIT意味着要大于该指定的文件单位,不能小于其文件本身,意味这并不包含该文件。

   -size [+|-]#UNIT(单位)
    常用单位:K, M, G
    
    #UNIT:(#-1, #]
    -#UNIT:[0, #-1]
    +#UNIT:(#, oo)     
        注:oo 正无穷

  那么我们接下来说根据其时间戳查找,这个是很麻烦的一项查找操作,它根据两类来进行查找,一类是以"天"为单位,另一类是以"分钟"单位。我们以天为单位为例,分为atime, mtime和ctime,atime为访问时间、mtime为内容修改时间、ctime为属性修改时间。而且它们也支持加或减的基本单位,我们就以atime为例。
  如果为#,意味着在当前时刻到过去的时间里,大于等于满足该条件,但不能大于该数字。例如,查找三天前的文件,意味着从现在开始,要大于等于三天,但不能超过四天。
  如果为-#,意味这在当前时刻到过去的时间里,小于则满足该条件,且不能超过该条件,例如,查找三天以内的文件。
  如果为+#,意味着在当前时刻到过去的时间里,大于则满足该条件,且超过了该条件的本身,例如,查找三天外的文件。

   以"天"为单位:
    -atime [+|-]#
        #:[#,#-1)
        -#:[#,#-1)
        +#:(#,oo)
    -mtime
    -ctime

   以"分钟"为单位:
    -amin
    -mmin
    -cmin

  那么接下来根据权限进行查找。

   -perm [/|-] mode
    mode:精确权限匹配;
    /mode:任何一类用户(u,g,o)的权限中的任何一位(r,w,x)符合条件即满足;(有一个就能符合)
        9位权限之间存在"或"关系;相反,全都没有;
    -mode:每一类用户(u,g,o)的权限中的每一位(r,w,x)同时符合条件即满足;都得必须有
        9位权限之间存在着"与"关系;相反,至少有一个没有;

3.2 处理动作

  以上说完查找条件之后,当查找完成之后,我们可以对结果进行一个处理的操作,例如除了默认显示之外,还可以产出或者保存信息等。那么常用的处理动作如下操作:

   处理动作:
    -print:输出至标准输出;默认的执行动作;
    -ls:类似于对查找的文件执行"ls -l"命令,输出文件的详细信息;
    -delete:删除查找到的文件;
    -fls /PATH/TO/SOMEFILE:把查找到的文件上长格式信息保存至指定文件中;
    -ok COMMAND {} \; :对查找到的每个文件执行由COMMAND表示的命令;每次操作都由用户进行确认;
    -exec COMMAND {} \; :对查找到的每个文件执行由COMMAND表示的命令;
        {}:引用查找到的文件名;

  例如:

   # find ./ -nouser -a -nogroup -ok chown root:root {} \;
   # find ./ -nouser -a -nogroup -exec chown root:root {} \; 
   # find ./ -user -perm /002 -exec mv {} {}.tmp \;

  需要注意的是,find查找到的文件量是非常大的,find传递查找到的文件路径至后面的命令时,是先查找出所有符合条件的文件路径,并一次性传递给后面的命令;但是有些命令不能接受过长的参数,此时命令执行会失败;另一种方式可规避此问题。

   # find | xargs COMMAND