一、了解find的基本含义及格式
 
find在我们所学英语中作动词时,有“发现、查找、找到等”含义,如今,在linux中“find”是文件查找命令,有实时、精确、支持众多查找标准的特点。
在查找文件时,因为find是遍历指定目录中的所有文件依次查找完成,查找速度相当慢,主要取决你查找的文件大小。 
格式:find 查找路径 查找标准 查找到以后的处理动作 
查找路径可以省略,默认为当前目录,如果是在其它目录下可以在find后面直接写你所在的目录
查找标准:默认为指定路径下的所有文件
查找到以后的处理动作:默认为显示到屏幕上
 
二、匹配查找标准 
1、根据文件名查找:
   -name ‘FILENAME’:对文件名作精确匹配
也支持文件名通配:
   *:表示匹配任意长度的任意字符
   ?:表示匹配任意单个字符
   [ ]:表示匹配范围内的任意单个字符
        [[:space:]]:所有空格字符
        [[:punct:]]:标点符号
        [[:lower:]]:小写字母
        [[:upper:]]:大写字母
        [[:digit:]]:数字
        [[:alnum:]]:数字和大小写字母
   [^]:托字符;匹配指定范围之外的任意单个字符
      -iname 'FILENAME':文件名匹配时不区分大小写
 
      -regex PATTERN:基于正则表达式进行文件名匹配,如果后面没有跟类型,默认为基本正则表达式
 
      -user USERNAME:根据属主查找,如果把某个用户的属主删除,以这个属主命名的文件的属主就会变成用户之前属主的ID号
      例如:#userdel -r hadoop
            #ls –l /tmp 再查看以hadoop为属主的用户就没有了
     
      -group GROUPNAME:根据属组查找与-user USERNAME含义一样
 
      -uid UID:根据UID查找
      例如:find /tmp –uid 2003 (表示查找/tmp下用户的uid为2003的文件)
 
      -gid GID:根据GID查找
      例如:find /tmp –gid 2003 (表示查找/tmp下用户的gid为2003的文件)
 
      -nouser:查找没有属主的文件
      例如:find /tmp –nouser (表示查找/tmp下没有属主的用户)
 
      -nogroup:查找没有属组的文件
      例如:find /tmp –nogroup (表示查找/tmp下没有属组的用户)
 
2、根据文件类型查找:
    -type 文件类型
文件类型:
          f:普通文件
          d: 目录文件
          b:块设备文件中可供存储的接口设备(block)
          c: 字符设备文件,如:键盘、鼠标 (character)
          l:符号链接文件(symbolic link file)
          p: 命令管道文件(pipe)
          s:套接字文件(socket)
 
3、根据文件的大小查找:
    -size [+|-] 如果不带单位默认为字节,想要显示查找到的文件大小可以使用ls
       #k:可以自己设定查找文件大小为多少k,可以与[+|-]一起使用
        +#k:表示文件大小在设定多少k以上的文件
        例如:find /var –size +10k (表示/var目录上文件大小在10k以上)
        -#k:表示文件大小在设定多少k以下的文件
        例如:find /var –size -10k (表示/var目录上文件大小在10k以下)
       
      #M:可以自己设定查找文件大小为多少M,可以与[+|-]一起使用
        +#M:表示文件大小在设定多少M以上的文件
        例如:find /var –size +10M (表示/var目录上文件大小在10M以上)
        -#M:表示文件大小在设定多少M以下的文件
        例如:find /var –size -10M (表示/var目录上文件大小在10M以下)
 
     #G:可以自己设定查找文件大小为多少G,可以与[+|-]一起使用
        +#G:表示文件大小在设定多少G以上的文件
        例如:find /var –size +10G (表示/var目录上文件大小在10G以上)
        -#G:表示文件大小在设定多少G以下的文件
        例如:find /var –size -10G (表示/var目录上文件大小在10G以下)
 
4、查找可以与组合条件一起使用:
       -a:与关系,如果没有说明组合条件默认为与关系
       例如:find /tmp -type d –a –type s (表示查找文件类型既属于目录又是套接字文件)
       -o:或关系   
       例如:find /tmp -type d –o –type s (表示查找文件类型属于目录或是套接字文件)  
       -not:非关系
       例如:find /tmp -not -type d   (表示查找文件类型不是目录)
      
5、根据修改时间戳查找:
       -mtime n:(单位为天),查找系统中n天被修改的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –mtime +5 (表示查找/tmp中至少5天被修改过的文件)
             find /tmp –mtime -5 (表示查找/tmp中5天内被修改过的文件)
 
       -ctime n:(单位为天),查找系统中n天被改变的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –ctime +5 (表示查找/tmp中至少5天被改变过的文件)
             find /tmp –ctime -5 (表示查找/tmp中5天内被改变过的文件)
 
       -atime n:(单位为天),查找系统中n天被访问的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –atime +5 (表示查找/tmp中至少5天被访问过的文件)
             find /tmp –atime -5 (表示查找/tmp中5天内被访问过的文件)
 
       -mmin n:(单位为分钟),查找系统中n分钟被修改过的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –mmin +5 (表示查找/tmp中至少5分钟被修改过的文件)
             find /tmp –mmin -5 (表示查找/tmp中5分钟内被修改过的文件)
 
       -cmin n:(单位为分钟),查找系统中n分钟被改变过的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –cmin +5 (表示查找/tmp中至少5分钟被改变过的文件)
             find /tmp –cmin -5 (表示查找/tmp中5分钟内被改变过的文件)
 
       -amin n:(单位为分钟),查找系统中n分钟被访问过的文件,可以与[+|-]#(数字)一起使用
       例如:find /tmp –amin +5 (表示查找/tmp中至少5分钟被访问过的文件)
             find /tmp –amin -5 (表示查找/tmp中5分钟内被访问过的文件)
 
6、通过文件权限查找:
    -perm MODE 精确匹配
        /MODE 文件权限符合任一位即可 (任意一位匹配即满足条件)
        例如:find ./ -perm /022 表示在家目录下组有写权限或者其它用户有写权限才能符合条件
 
       -MODE 文件权限能完全包括此MODE才符合条件,有包含关系 (对应的位必须完全匹配)
        例如:find ./ -perm -001 表示在家目录下只有其它用户有执行权限
思考:find ./ -perm -644 如果是权限为755、750的文件能匹配到吗?
分析:      644:rw-r--r--
            755:rwxr-xr-x
            750:rwxr-x---
只要权限为644的位,权限755都满足而权限为750不包含其它用户的位,所以权限为755的文件能匹配到而权限为750的文件不能匹配
在-perm前加-not,就代表后面的-001表示相反的意思(任意一位匹配即满足条件)
      
三、根据查找到文件对其以后的处理动作
       1、 -print:显示
       2、-ls:类似ls -l的形式显示每一个文件的详细
       3、-ok COMMAND {} \;每一次操作都需要用户确认(只要引用刚找到的文件名就要使用{})
       例如:find ./ -type d –ok chmod +x {} \; 表示查找家目录下文件类型为目录并且属主、属组、其它赋予执行权限的文件
       4、-exec COMMAND {} \;而exec不需要用户确认
       例如:find ./ -perm -006 –exec chmod o-w {} \; 表示查找家目录下其它用户有写读权限的文件并把写权限去掉
             find ./ -perm -020 –exec mv {} {}.new \; 表示查找家目录下属组有写权限的文件改为文件后加一个.new
      5、xargs:从标准输入接收命令并执行,通过管道送给xargs而且执行的命令放到其后面即可,使用xargs命令时后面不加{}和\
      例如:find /etc –size +1M –exec echo {} >> /tmp/etc.largefiles \;表示查找/etc目录下文件大小为1M的文件追加到/tmp/etc.largefiles中
      或者  find /etc –size +1M | xargs echo >> /tmp/etc.largefiles
但使用xargs命令追加到/tmp/etc.largefiles中的内容不是一行一行显示,而是以空格隔开
 
牛刀小试:
1、查找/var目录下属主为root并且属组为mail的所有文件;
find /var -user root -group mail
2、查找/usr目录下不属于root,bin,或student的文件;
find /usr -not \( -user root -o -user bin -o -user student \)
3、查找/etc目录下最近一周内内容修改过且不属于root及student用户的文件;
find /etc -mtime -7 -not \( -user root -o -user student \)
4、查找当前系统上没有属主或属组且最近1天内曾被访问过的文件,并将其属主属组均修改为root;
find ./ \( -nouser -o -nogroup \) -a -atime -1 -exec chown root:root {} \;
5、查找/etc目录下大于1M的文件,并将其文件名写入/tmp/etc.largefiles文件中;
find /etc -size +1M >> /tmp/etc.largefiles
6、查找/etc目录下所有用户都没有写权限的文件,显示出其详细信息;  
find /etc -not -perm /222 –ls
 
剖析例题:
写一个脚本,可以接受选项及参数,而后能获取每一个选项,及选项的参数;并能根据选项及参数做出特定的操作,比如:
adminusers.sh --add tom,jerry --del tom,jerry blair -v|--verbose -h|--help
脚本内容
#!/bin/bash
#
DEBUG=0     @定义三个变量的初始值分别都为0【相当于三个开关】
ADD=0
DEL=0
for I in `seq 1 $#`; do @由于不知道输入的参数个数,可用$#代表将来要输入的参数个数,然后定义变量让它从1循环执行
case $1 in        @如果输入的第一个参数在以下选项中出现,则执行相应的操作    
-v|--verbose)      @如果第一个参数是—v|--verbose就把变量DEBUG=1【相当于开启这个参数的功能】,然后踢出,其后面的参数就变成第一个参数
DEBUG=1
shift ;;
-h|--help)         @如果第一个参数是-h|--help就显示帮助信息,并以0作为退出验证码【表示输出正确】
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0 ;;
--add)           @如果第一个参数是--add,就把变量ADD的开关打开,然后把第二个参数输出的执行值赋给ADDUSERS,之后把这两个参数踢出
ADD=1
ADDUSERS=$2
shift 2 ;;
--del)           @如果第一个参数是--del,就把变量DEL的开关打开,然后把第二个参数输出的执行值赋给DELUSERS,之后把这两个参数踢出
DEL=1
DELUSERS=$2
shift 2;;
*)             @如果是其它的参数则输出帮助信息,并以7作为退出验证码【表示错误输出,错误输出的退出验证码可以在(1-255)之间】
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7 ;;
esac
done
if [ $ADD -eq 1 ]; then @如果变量ADD的输出值等于1,就执行下面的操作
for USER in `echo $ADDUSERS | sed 's/,/ /g'`; do    @定义一个存储用户的变量USER,用户之间的“,”替换成空格
if id $USER &> /dev/null; then    @如果用户的id信息存在,其结果对我们没有什么作用,可以把它丢到/dev/null中
[ $DEBUG -eq 1 ] && echo "$USER exists." @如果DEBUG的返回值等于1同时会显示某某用户已存在
else
useradd $USER    @否则,就会添加该用户
[ $DEBUG -eq 1 ] && echo "Add user $USER finished."   @如果DEBUG的返回值等于1就会显示添加该用户已完成
 fi
done
fi
if [ $DEL -eq 1 ]; then    @如果DEL的返回值等于1,就会执行下面的操作
for USER in `echo $DELUSERS | sed 's/,/ /g'`; do   @定义一个删除用户的变量USER,用户之间的“,”替换成空格
if id $USER &> /dev/null; then     @如果用户的id信息存在,其结果对我们没有什么作用,可以把它丢到/dev/null中
userdel -r $USER    @我们就删除该用户
[ $DEBUG -eq 1 ] && echo "Delete $USER finished."   @如果DEBUG的返回值等于1,同时会显示删除该用户已完成
else
[ $DEBUG -eq 1 ] && echo "$USER not exist."   @否则,就会显示该用户不存在
 fi
done
fi

提示:为了避免混淆,我使用@符号代表注释信息!