一. name 选项
文件名选项是 find 命令最常用的选项, 要么单独使用该选项, 要么和其他选项一起使用. 可以使用某种文件名模式来匹配文件, 记住要用引号将文件名模式引起来. 不管当前路径是什么, 如果想要在自己的根目录 $HOME 中查找文件名符合 *.log 的文件, 使用~ 作为'pathname'参数, 波浪号~ 代表了你的 $HOME 目录.
find ~ -name "*.log"
想要在当前目录及子目录中查找所有的'*.log'文件, 可以用:
find . -name "*.log"
想要的当前目录及子目录中查找文件名以一个大写字母开头的文件, 可以用:
find . -name "[A-Z]*"
想要在 / etc 目录中查找文件名以 host 开头的文件, 可以用:
find /etc -name "host*"
想要查找 $HOME 目录中的文件, 可以用:
find ~ -name "*"
要想让系统高负荷运行, 就从根目录开始查找所有的文件.
find / -name "*"
如果想在当前目录查找文件名以一个个小写字母开头, 最后是 4 到 9 加上. log 结束的文件:
命令:
find . -name "[a-z]*[4-9].log" -print
二. perm 选项
按照文件权限模式用 - perm 选项, 按文件权限模式来查找文件的话. 最好使用十进制的权限表示法.
如在当前目录下查找文件权限位为 755 的文件, 即文件属主可以读, 写, 执行, 其他用户可以读, 执行的文件, 可以用:
find . -perm 755
find -perm, 根据文件的权限来查找文件, 有三种形式:
- find -perm mode
- find -perm -mode
- find -perm +mode
那么这三者之间有什么区别呢? 解释之前首先得简单说一下 Linux 中文件权限位的概念. 在 Linux 中文件或目录有三者权限 r,w,x, 代表的含义分别是读, 写, 可执行. 而一个文件或目录的属性中又包括所属用户 u, 所属组 g, 其他 o 三个部分的属性, 分别表示所属用户, 所属组, 其他用户对这个文件所拥有的权限. 看起来大概是这个样子:
所属用户 所属组 其他
rwx rwx rwx
用户在其拥有权限的位上设置 1, 没有权限的位设置 0. 如果将每个部分的这些权限位看成二进制数, 每个部分可以用 3 位二进制数表示, 最大值为 7(2^3-1), 表示可读, 可写, 可执行. 严格的来说, 文件权限除了 r,w,x 以外还有 setuid,setgid 权限, 等下再解释.
好了, 有了权限位的基础, 那么再来看 find -perm mode.mode 是三个数字表示的, 每个数字最大值是 7(原因前面解释过了).
find -perm mode , 表示严格匹配, 也就是你的文件权限位转换成对应的十进制数字与 mode 一模一样, 那么匹配成功, 需要注意的是如果 mode 给的数字不足 3 位, 那么前面自动添 0(严格的说是不足 4 位, 原因就是前面所说的 setuid,setgid, 稍后解释)
find -perm -mode , 表示 mode 中转换成二进制的 1 在文件权限位里面必须匹配, 比如 mode=644 那么转换成二进制为 110 100 100, 而被查找的文件的权限位也可以被转换成一个二进制数, 两者在位上为 1 的部分必须完全匹配, 而 0 则不管. 例如被查找的文件的权限为转换成二进制数是 111 111 111 那么这个比如被匹配, 而假如是 100 100 100 那么则不会匹配. 所以这个'-'的作用归结起来就是匹配比 mode 权限更充足的文件(找不到什么词语来形容了)
find -perm +mode , 与 -mode 的区别是 + mode 只需其中的任意一个 1 的部分被匹配,-mode 是所有 1 的部分都必须被匹配, 同样 + mode 也不管 0 位.
现在来解释 setuid,setgid,setuid 权限是用来使其他用户可以 "越权" 执行你的命令, 而本质上的实现就是在权限检查的时候, 在进程的的有效 UID 里面保存了这个其他用户的 UID, 所以权限得意验证通过 (在这里的 http://www.2cto.com/os/201205/130111.html 注释 1 里面很简单的介绍了一下), 这些权限用一个新的 3 位二进制数表示, 有 4,2,1 三种值, 4 表示有 setuid 权限, 2 表示有 setgid 权限, 1 表示有粘着位(t) 权限 (粘着位权限最典型的例子是 / tmp, 每个用户可以在里面创建, 更新, 删除自己创建(文件所属用户是自己) 的文件, 而不能更改别人的文件).
- $ ls -l
- total 0
- -rwxrwxrwx 1 fai root 0 Aug 28 15:15 a
- -rwxr-xr-x 1 fai root 0 Aug 28 15:15 b
- ----rw---- 1 fai root 0 Aug 28 15:15 c
- -rw-rw-rw- 1 fai root 0 Aug 28 15:15 d
- -r-xr--r-- 1 fai root 0 Aug 28 15:15 e
对于权限进行十进制转 2 进制
- a(777):111 111 111
- b(755):111 101 101
- c(060): 000 110 000
- d(666):110 110 110
- e(544):101 100 100
- $ find . -perm +006
- .
- ./b
- ./d
- ./a
- ./e
mode 中的 006 转为 2 进制是: 000 000110
根据部分匹配的原则, 只要在第 3 组中的第一或者第二位出现 1 就可以了, 所以看到 e 文件 101 只是匹配了第一位的 1, 但是也打印了. 而 a 文件 111 的情况更是符合这个说法了. 注意: c 文件虽然出现了 110, 但是不是对应的组, 这个匹配是在相应位的.
- $ find . -perm -006
- ./d
- ./a
对于 - perm -006, 也同样道理去判断, 只是这里需要完全匹配, 也就是 mode 的二进制中出现 1 的地方, 目标中也要出现才行
需要在最后一组中的第一和第二位同时出现 1 才能匹配.
- a(777):111 111 111
- d(666):110 110 110
三. prune 选项(此处引用 http://blog.sina.com.cn/s/blog_6ad648f30100tqwy.html)
查找时忽略指定目录, 是要使用 - prune 选项, 但实际上最重要的还是要和 path 配合.-prune 的意义是, 当路径字串匹配了 path 中指定的目录时 候, find 命令不进入这个目录查找, 所以这个选项使用的关键, 还是在 path 选项上的使用, 也就是 path 选项和其他选项的配合使用, 才能最后确定最终 结果. 而 path, 实际上是对路径字串的一个字符匹配, 但也并不仅仅只匹配于目录, 文件同样可以被匹配, 譬如存在一个目录结构.
- ./01.txt
- ./02.txt
- ./03.txt
- ./aaa
- ./aaa/04.txt
- ./aaa/05.txt
find . -path "./aaa" -print 匹配中使用通配符, 则会输出
- ./aaa
- ./aaa/04.txt
- ./aaa/05.txt
而如果是 find . -path "./aaa" -print , 严格等于./aaa 目录, 则只输出
./aaa
而且 * 通配符会将路径中的字符 "/" 也作为普通字符进行贪婪匹配, 所以可以匹配到目录以下的文件, 所以在使用这个选项时候不要误以为这个只对目录有效, 实际上只是一种路径字符匹配工具.
1. 查找文件时, 忽略某个目录
如果加上 - prune, 则第一个命令效果是:
- find . -path "./aaa*" -prune -print
- ./aaa
因为加入了 - prune, 在匹配这个目录同时禁止进入到这个目录下搜索, 于是也就是我们所需要的不进入某个目录查找.
但如何配合其他选项来使用 - path 以及 - prune 呢? 以 - name 为例, 下面对于配合使用方法进行一下演示.
我们先来看看纯粹的 - name 和 - path 配合使用是什么效果:
find -name "*.txt" -path "./aaa" -print
这个命令也相当于
find -name "*.txt" -a -path "./aaa" -print
但一般的 - a 都被忽略不写. 这个命令对于上面的目录结构这个命令执行为空结果. 也就是, 既要文件名称匹配 ".txt", 同时又要其路径字 串匹配 "./aaa", 而文件名匹配 ".txt" 的结果有:
- ./01.txt
- ./02.txt
- ./03.txt
- ./aaa/04.txt
- ./aaa/05.txt
路径字串匹配 "./aaa" 的只有
./aaa
二者取 and 则为空结果, 所以上面的命令输出为空.
如果对 - path 选项加上 - prune
find -name "*.txt" -path "./aaa" -prune -print
实际上与上面那条命令输出并无区别, 只是禁止进入./aaa 下匹配而已, 但最终的结果仍然是空.
再来看看很多人会误用的结构:
find -name "*.txt" -path "./aaa" -prune -o -print
也就是比上一条语句在 - print 前增加一个 - o. 但实际上这条命令是将当前目录以及包含./aaa 子目录下的所有文件都打印出来. 实际上
, 这个语句先执行 - o 左侧的语句, find -name "*.txt" -path "./aaa" -prune, 因为匹配为空, 则执行 - o 右侧的语句 - print, 也就是把不匹配左侧的文件名打印出来, 既然左侧没有匹配为真的, 所以也就是所有的文件都被打印.
这里要留意的是匹配模式项 (比如 - name "*.txt", -path ....), 关系符( -a, -o, ","), 与操作符(-print, -exec,- ok) 之间的位置关系, 特别是操作符在关系符的不同位置上, 对于结果也具有决定的作用.
说明:
find [-path ..] [expression]
在路径列表的后面的是表达式
-path "test" -prune -o -print 是 -path "test" -a -prune -o -print 的简写表达式按顺序求值, -a 和 -o 都是短路求值, 与 shell 的 && 和 || 类似如果
-path "test" 为真, 则求值 -prune , -prune 返回真, 与逻辑表达式为真; 否则不求值 -prune, 与逻辑表达式为假. 如果 -path "test" -a -prune 为假, 则求值 -print ,-print 返回真, 或逻辑表达式为真; 否则不求值 -print, 或逻辑表达式为真.
这个表达式组合特例可以用伪码写为:
- if -path "test" then
- -prune
- else
比如一个语句
find -name "*.txt" -print -o -path "./aaa" -prune -print (1)
其实也可以略写为
find -name "*.txt" -o -path "./aaa" -prune
注意第二个语句 - o 两侧都没有 - print, 输出结果为:
- ./01.txt
- ./02.txt
- ./03.txt
- ./aaa
这是因为 find 开始执行, 遇到第一个 - print 命令, 则会考虑输出, 但是输出的时候, 则是将剩余所有的匹配项一起进行匹配操作, 也就是执行的是
find -name "*.txt" -print -o -path "./aaa" -prune (注意 - print 命令的位置)
这个命令执行中相当于
find -path "./aaa" -prune -o -name "*.txt" -print
也 就是在匹配过程中, 对于包含了 - print 部分的匹配项是最后匹配的, 因此先匹配到了./aaa 路径, 由于 - prune 的存在禁止进入这个路径查找, 禁止 进入查找, 并不会因为 - o 选项而被逆转, 所以左侧匹配了./aaa 后,-o 右侧则是不匹配./aaa 项目剩余的文件继续去匹配 - name 模式, 匹配的结果 最后被 - print 打印出来, 这也就是我们所期待的忽略某个指定目录进行搜索的结果.
但是我们要分析的是命令 (1) 中的结果, 命令 (1) 在遇到第一个 - print 命令后并执行了输出, 但是这个 find 命令中还存在第二个 - print 命令, 所以在输出
- ./01.txt
- ./02.txt
- ./03.txt
结果后, 还是要继续执行, 要执行最后一个 - print 命令, 下面的执行则相当于执行一个
find -name "*.txt" -o -path "./aaa" -prune -print
-o 左侧匹配 - name "*.txt",-o 到右侧后则是对不能匹配到 - name 模式的结果, 进行 - path 匹配, 输出结果为
./aaa
所以 (1) 命令最终的输出结果就是
- ./01.txt
- ./02.txt
- ./03.txt
- ./aaa .
2. 忽略多个文件夹
-a, -o 都常见了, 但是实际中还可以存在 "," 的使用, 例如新建一个 aaa1 目录, 其下有 08.txt 等文件, 若执行
- $ find -name "*.txt"
- ./01.txt
- ./02.txt
- ./03.txt
- ./aaa/04.txt
- ./aaa/05.txt
- ./aaa1/08.txt
- ./aaa1/09.txt
若忽略 aaa 和 aaa1 目录查找 txt 文件, 则可以写做
- $ find -name "*.txt" -print -o -path "./aaa" -prune , -path "./aaa1" -prune (注意 "," 两侧的空格不可忽略)
- ./01.txt
- ./02.txt
- ./03.txt
这也就是同时忽略几个目录的写法, 注意每忽略一个目录, 其后都要跟随一个 - prune, 而不能几个 - path 公用一个 - prune.
其实若没有 - prune 的使用, 也可以忽略某个目录下文件的匹配, 譬如
- $find -path "./aaa*" -o -name "*.txt" -print
- ./01.txt
- ./02.txt
- ./03.txt
同样可以不匹配到./aaa 目录下的文件, 但是这里实际上是搜索过./aaa 目录下的文件并且进行匹对的, 只是因为 - print 在 - o 的右侧输出, 而./aaa 下的文件被匹配是在 - o 的左侧, 所以最终的结果是达不到被打印输出的条件. 但效率应当是明显低于使用 - prune 选项.
四. user 和 nouser 选项
1. 在 $HOME 目录中查找文件属主为 hc 的文件
find ~ -user hc -print
2. 在 / etc 目录下查找文件属主为 hc 的文件:
命令:
find /etc -user hc -print
3. 为了查找属主帐户已经被删除的文件, 可以使用 - nouser 选项. 在 / home 目录下查找所有的这类文件
find /home -nouser -print
说明:
这样就能够找到那些属主在 / etc/passwd 文件中没有有效帐户的文件. 在使用 - nouser 选项时, 不必给出用户名; find 命令能够为你完成相应的工作.
五.使用 group 和 nogroup 选项:
就像 user 和 nouser 选项一样, 针对文件所属于的用户组, find 命令也具有同样的选项, 为了在 / apps 目录下查找属于 Gem 用户组的文件, 可以用:
find /apps -group Gem -print
要查找没有有效所属用户组的所有文件, 可以使用 nogroup 选项. 下面的 find 命令从文件系统的根目录处查找这样的文件:
find / -nogroup -print
六.按照更改时间或访问时间等查找文件:
如果希望按照更改时间来查找文件, 可以使用 mtime,atime 或 ctime 选项. 如果系统突然没有可用空间了, 很有可能某一个文件的长度在此期间增长迅速, 这时就可以用 mtime 选项来查找这样的文件.
用减号 - 来限定更改时间在距今 n 日以内的文件, 而用加号 + 来限定更改时间在距今 n 日以前的文件.
希望在系统根目录下查找更改时间在 5 日以内的文件, 可以用:
find / -mtime -5 -print
为了在 / var/adm 目录下查找更改时间在 3 日以前的文件, 可以用:
find /var/adm -mtime +3 -print
七.查找比某个文件新或旧的文件:
如果希望查找更改时间比某个文件新但比另一个文件旧的所有文件, 可以使用 - newer 选项.
它的一般形式为:
newest_file_name ! oldest_file_name
其中,! 是逻辑非符号.
1. 查找更改时间比文件 log1 新但比文件 log3 旧的文件
命令:
find -newer log1 ! -newer log3
2. 查找当前目录下更改时间在比 log2 文件新的文件
命令:
find . -newer log2 -print
八.使用 type 选项:
1: 在 / etc 目录下查找所有的目录
命令:
find /etc -type d -print
2: 在当前目录下查找除目录以外的所有类型的文件
命令:
find . ! -type d -print
3: 在 / etc 目录下查找所有的符号链接文件
命令:
find /etc -type l -print
九.使用 size 选项:
可以按照文件长度来查找文件, 这里所指的文件长度既可以用块 (block) 来计量, 也可以用字节来计量. 以字节计量文件长度的表达形式为 N c; 以块计量文件长度只用数字表示即可.
在按照文件长度查找文件时, 一般使用这种以字节表示的文件长度, 在查看文件系统的大小, 因为这时使用块来计量更容易转换.
1: 在当前目录下查找文件长度大于 1 M 字节的文件
命令:
find . -size +1000000c -print
2: 在 / home/apache 目录下查找文件长度恰好为 100 字节的文件:
命令:
find /home/apache -size 100c -print
3: 在当前目录下查找长度超过 10 块的文件(一块等于 512 字节)
命令:
find . -size +10 -print
十.使用 depth 选项:
在使用 find 命令时, 可能希望先匹配所有的文件, 再在子目录中查找. 使用 depth 选项就可以使 find 命令这样做. 这样做的一个原因就是, 当在使用 find 命令向磁带上备份文件系统时, 希望首先备份所有的文件, 其次再备份子目录中的文件.
1:find 命令从文件系统的根目录开始, 查找一个名为 CON.FILE 的文件.
命令:
find / -name "CON.FILE" -depth -print
说明:
它将首先匹配所有的文件然后再进入子目录中查找
十一.使用 mount 选项:
在当前的文件系统中查找文件(不进入其他文件系统), 可以使用 find 命令的 mount 选项.
1: 从当前目录开始查找位于本文件系统中文件名以 XC 结尾的文件
命令:
find . -name "*.XC" -mount -print
来源: https://www.cnblogs.com/huchong/p/9967818.html