find命令用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录 名。如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件。 并且将查找到的子目录和文件全部进行显示。

1. 用法

1
find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

简化版本

1
2
find [path] -options [-print -exec -ok ...]
find [path][expression]
  1. path是所要查找的目录路径,默认为当前目录

  2. 默认表达式为 -print,将匹配到的文件输出到标准输出;

  3. 表达式可能由下列成份组成:操作符选项测试表达式以及动作

  4. execfind命令对匹配到的文件执行该参数所给出的形式为 command {} \;的shell 命令 加上 -ok 则更安全的执行命令,执行前需要进行确认。

2. 功能

find命令用于在文件树种查找文件,并作出相应的处理

如果只是根据文件名查找文件,使用locate更快,而且命令也更简单

3. 表达式详解

表达式可能由下列成份组成:操作符选项测试表达式以及动作.

操作符

优先级递减;未做任何指定时默认使用 -and):

  • ( EXPR )
  • ! EXPR
  • -not EXPR
  • EXPR1 -a EXPR2
  • EXPR1 -and EXPR2
  • EXPR1 -o EXPR2
  • EXPR1 -or EXPR2
  • EXPR1 , EXPR2

位置选项

总是真:

1
2
3
-daystart                      # 从本日开始计算时间;
-follow                        # 排除符号连接;
-regextype

普通选项

总是真,在其它表达式前指定:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-depth                         # 从指定目录下最深层的子目录开始查找;
--help
-maxdepth LEVELS               # 设置最大目录层级
-mindepth LEVELS               # 设置最小目录层级
-mount                         # 和指定"-xdev"相同
-noleaf                        # 不去考虑目录至少需拥有两个硬连接存在
--version
-xdev                          # 将范围局限在先行的文件系统中
-ignore_readdir_race
-noignore_readdir_race

比较测试

设定要查找的文件满足的条件,N 可以是 +N 或 -N 或 N:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
-amin N                        # 查找指定时间内被存取过的文件,以分钟为单位
-anewer FILE                   # 查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录;
-atime N                       # 查找在指定时间曾被存取过的文件或目录,单位以24小时计算;
-cmin N                        # 查找在指定时间之时被更改过的文件或目录;
-cnewer 文件                   # 查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录;
-ctime N                       # 查找在指定时间之时被更改的文件或目录,单位以24小时计算;
-empty                         # 寻找文件大小为0 Byte的文件,或目录下没有任何子目录或文件的空目录;
-false                         # 将find指令的回传值皆设为False
-fstype 类型                   # 只寻找该文件系统类型下的文件或目录;
-gid N                         # 查找符合指定之群组识别码的文件或目录;
-group 名称                    ## 按照文件所属的组来查找文件。
-ilname 匹配模式               # 和指定"-lname"参数类似,但忽略字符大小写的差别
-iname 匹配模式                # 和指定"-name"参数类似,但忽略字符大小写的差别
-inum N                        # 查找符合指定的inode编号的文件或目录;
-ipath 匹配模式                # 和指定"-path"参数类似,但忽略字符大小写的差别
-iregex 匹配模式               # 和指定"-regex"参数类似,但忽略字符大小写的差别
-links N                       # 查找符合指定的硬连接数目的文件或目录
-lname 匹配模式
-mmin N                        # 查找在指定时间曾被更改过的文件或目录,单位以分钟计算
-mtime N                       ## 按照文件的更改时间来查找文件
-name 匹配模式                 ## 按照文件名查找文件。
-newer FILE1 [!FILE2]          ## 查找更改时间比文件file1新,[但比文件file2旧]的文件。
-nouser                        ## 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
-nogroup                       ## 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在
-path PATTERN                  ## 指定字符串作为寻找目录的范本样式
-perm [-/]MODE                 ## 按照文件权限来查找文件
-regex PATTERN                 # 指定字符串作为寻找文件或目录的范本样式
-readable                      # 可读?
-writable                      # 可写?
-executable                    # 可执行?
-wholename PATTERN
-size N[bcwkMG]                ## 按照文件大小查找文件
-true                          # 将find指令的回传值皆设为True
-type [bcdpflsD]               ## 查找某一类型的文件
-uid N                         # 查找符合指定的用户识别码的文件或目录
-used N                        # 查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算;
-user NAME                     ## 按照文件属主来查找文件。
-xtype [bcdpfls]               # 和指定"-type"参数类似,差别在于它针对符号连接检查
-context 文本

操作:

假设find指令的回传值为Ture,就执行相应的命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-delete                         # 假设find指令的回传值为Ture,就将文件删除
-print0                         # 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行
-printf 格式                    # 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式可以自行指定;
-fprintf 文件 格式              # 和指定"-print"参数类似,但会把结果保存成指定的列表文件;
-print                          # 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式为每列一个名称,每个名称前皆有"./"字符串;
-fprint0 文件                   # 和指定"-print0"参数类似,但会把结果保存成指定的列表文件;
-fprint 文件                    # 和指定"-printf"参数类似,但会把结果保存成指定的列表文件;
-ls                             ## 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出
-fls 文件
-prune -quit                    ## 使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略
-exec 命令 ;                    ## 假设find指令的回传值为True,就执行该指令;
-exec 命令 {} + -ok 命令 ;
-execdir 命令 ;
-execdir 命令 {} + -okdir 命令 ;

与xargs结合

在使用find命令的-exec选项处理匹配到的文件时,有如下的问题:

  • find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令 长度有限制,就会出现溢出错误,错误信息通常是”参数列太长”或”参数列溢出”。
  • 在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并 非将匹配到的文件全部作为参数一次执行;在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;

这些问题的解决办法是使用xargs命令:

  • find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全 部,可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
  • 使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数, 还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。

find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令

4. 一些实例

按文件名或正则表达式进行匹配

1
2
3
4
5
6
7
8
9
find .                                          ## 列出当前目录及子目录下的所有文件和文件夹
find /home -name "*.txt"                        ## 在 /home 目录下查找所有以 .txt 结尾的文件
find /home -iname "*.txt"                       ## 同上,但忽略大小写
find /home ! -name "*.txt"                      ## 否定参数,找出不以 .txt 结尾的文件
find . \( -name "*.txt" -o -name "*.pdf" \)
find . -name "*.txt" -o -name "*.pdf"           ## 查找当前目录及子目录下的所有以 .txt 和  .pdf 结尾的文件
find /usr/ -path "*local*"                      ## 匹配文件路径或者文件
find . regex "."\(\.txt\|\.pdf\)$"              ## 基于正则表达式匹配文件路径
find . iregex  "."\(\.txt\|\.pdf\)$"           ## 同上,但忽略大小写

按文件类型搜索

1
2
3
4
5
6
7
find . -type 类型参数            ## f 普通文件
                                    l 符号连接
                                    d 目录
                                    c 字符设备
                                    b 块设备
                                    s 套接字
                                    p Fifo

基于目录深度搜索

1
2
find . -maxdepth 3 -type f        ## 最大深度限制为3
find . -mindepth 2 -type f        ## 搜索出深度距离当前目录至少2个子目录的所有文件

按文件时间进行搜索

Linux下文件的三种时间:

  • 访问时间(-atime/天,-amin/分钟):用户最近一次访问时间。
  • 修改时间(-mtime/天,-mmin/分钟):文件最后一次修改时间。
  • 变化时间(-ctime/天,-cmin/分钟):文件数据元(例如权限等)最后一次修改时间。
1
2
3
4
find . -type f -atime -7                        ## 搜索最近七天内被访问过的所有文件
find . -type f -atime 7                         ## 搜索恰好在七天前被访问过的所有文件
find . -type f -atime +7                        ## 搜索超过七天内被访问过的所有文件
find . -type f -newer long.log !short.log       ## 找出比long.log修改时间更长但比short.log短的所有文件

按文件大小进行匹配

1
2
3
find . -empty                                    ## 列出当前目录及子目录下所有长度为零的文件
find . -type f -size 文件单元大小(+N N -N)(单位) ## 搜索大于 等于 小于 N(单位)的文件
## 单位:b:块(512字节);c:字节;w:字(2字节);k:千字节;M:兆字节;G:吉字节;

根据文件权限/所有权匹配

1
2
3
4
find . -type f -perm 777                          ## 查找当前目录下权限为777的文件
find . -type f -name "*.php" ! -perm 644          ## 找出当前目录下权限不是644的php文件
find . -type f -user tom                          ## 找出当前目录下用户tom所拥有的文件
find . -type f -group sunk                        ## 找出当前目录下用户组sunk拥有的文件

查找文件并执行命令

当查找出文件后,即返回值为True时,可以对找出的文件进行操作,操作方式有3种类型:

  • 是内建的delete,ls,print等命令;
  • 是借助-ok-exec选项与其他命令结合使用,{}用来代替匹配出的所有文件,并以\;结尾
  • 借助xargs命令
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
find . -type f -name "*.txt" -delete                    ## 删除当前目录下所有.txt文件
find . -type f -name "*.txt" -exec rm {} \;             ## 同上
find . -type f -name "*.txt" | xargs rm                 ## 同上
find . -type f -name "*.txt" -ok rm {} \;               ## 同上,但要求进行确认
find . -type f -user root -exec chown tom {} \;         ## 找出当前目录下所有root的文件,并把所有权更改为用户tom
find . -type f -name "*.txt" -exec cat {} \;> all.txt   ## 查找当前目录下所有.txt文件并把他们拼接起来写入到all.txt文件中
## 将30天前的.log文件移动到old目录中
find . -type f -mtime +30 -name "*.log" -exec cp {} old \;
## 找出当前目录下所有.txt文件并以"File:文件名"的形式打印出来
find . -type f -name "*.txt" -exec printf "File: %s\n" {} \;
## 找出当前目录下所有.txt文件并以"File:文件名"的形式打印出来
find . -type f -name "*.txt" -exec printf "File: %s\n" {} \;

5. 寻求帮助

  • 使用 find --help
  • 使用 man find
  • 使用 info find

参考链接

  1. http://www.cnblogs.com/peida/archive/2012/11/13/2767374.html
  2. http://man.linuxde.net/find