查找文件
一、语法格式
find [path] [expression]
功能:从指定的目录开始,递归地搜索其子目录,查找满足条件的文件并操作之
[path]表示从此目录开始搜索
[expression]是一个选项表达式,是一系列选项。最基本的选项表达式分为三类:设置项(option)、测试项(test)、动作项(action),这三类又可以通过逻辑运算符(operator)组合在一起。
二、运算符
运算符是连接选项的符号。
逻辑运算符:按照优先级从高到低的顺序
- 括号
( expr ) - 非
! EXPR 或者 -not EXPR - 与
EXPR1 -a EXPR2 或者 EXPR1 -and EXPR2 或者 expr1 expr2 中间不加任何运算符。expr1为真,要接着执行expr2;expr1为假,则不再执行expr2。 - 或
EXPR1 -o EXPR2 或者 EXPR1 -or EXPR2。expr1为真,不再执行expr2;expr1为假,要接着执行expr2。 - 逗号
expr1 , expr2 expr1和expr2都会求值,但是只返回expr2的值,expr1的值会被丢弃
三、选项
(一)设置项:
设置项针对这次查找任务,而不是仅仅针对某一个文件,设置项总是返回true
位置选项
-daystart -follow -nowarn -regextype -warn
普通选项
-depth -files0-from FILE -maxdepth LEVELS -mindepth LEVELS
-mount -noleaf -xdev -ignore_readdir_race -noignore_readdir_race
-xautofs
(二)测试项:
测试项(test)则不同,它针对具体的一个文件,测试文件是否满足测试条件。如-name,-num,-user等,返回true或者false
-amin N
-anewer FILE
-atime N
-cmin N
-cnewer FILE
-context CONTEXT
-ctime N
-empty
-false
-fstype TYPE
-gid N
-group NAME
-ilname PATTERN
-iname PATTERN
-inum N
-iwholename PATTERN
-iregex PATTERN
-links N
-lname PATTERN
-mmin N
-mtime N
-name PATTERN
-newer FILE
-nouser
-nogroup
-path PATTERN
-perm [-/]MODE
-regex PATTERN
-readable
-writable
-executable
-wholename PATTERN
-size N[bcwkMG]
-true
-type [bcdpflsD]
-uid N
-used N
-user NAME
-xtype [bcdpfls]
(三)动作项:
动作项(action)也是针对具体的一个文件,对文件做某种动作(最常见的如-print),返回true或者false
-delete
-print0
-printf FORMAT
-fprintf FILE FORMAT
-print
-fprint0 FILE
-fprint FILE
-ls
-fls FILE
-prune
-quit
-exec COMMAND ;
-exec COMMAND {} + -ok COMMAND ;
-execdir COMMAND ;
-execdir COMMAND {} + -okdir COMMAND ;
四、示例
1.基本用法
find
find .
两个都是查找当前目录下的所有文件。
2.-name 指定文件名查找文件
-name属于表达式中的测试项(test),它按照文件名模式?*[]来匹配文件,若匹配则返回true,否则返回false。
最好用引号将文件名模式引起来,防止shell解析模式字符串。如果由shell解析模式,*
不会匹配开头的点,而由find解析的话,*是能匹配开头的点的。
也就是说,find . -name *txt
与find . -name '*txt'
是不同的。前者不匹配.txt文件,而后者匹配.txt文件。
使用-name时,*是不匹配/的
find -name 'Test*'
查找当前目录下文件名以Test开头的文件
find / -name 'temp' -o -name 'install*'
在根目录下查找文件名为temp或是匹配install*的所有文件
find ! -name 'Test*'
在当前目录下查找不以Test开头的文件
find . -name "*.txt" -o -print
如果表达式-name "*.txt"为真,就不再执行另一个表达式-print,即查找所有不是以.txt结尾的文件。
find . -name "*e*[0-9]*" ! -type d -print
查找当前目录下,文件名中包括字母'e',在'e'之后又有数字的不是目录文件的所有文件
find . -name "[A-Za-b]*"
当前目录及子目录中查找文件名以一个大写字母开头或者以小写a或b开头的文件
-iname
-name区分大小写,如果不想区分大小写可以使用-iname测试项。
'i'可以加在许多选项前面,比如-ipath,-iregex,-iwholename等等,都是不区分大小写。
3.-path指定路径名查找文件
-path属于测试项(test)。指定全路径名进行查找。它也是按照文件名模式?*[]
来匹配
全路径名可以是相对路径和绝对路径,如果写相对路径必须加上./
也要把模式字符串用引号引起来,防止shell解析。
使用-path时,*是匹配/的。
find . -path '*phone/pu*'
当前目录下有一个phone目录,phone目录里有一个文件名称是puk.txt,此命令在当前目录下的phone目录查找pu开头的的文件
find . -path '*s*/*p'
能匹配
sw/in/kp
sf/fw/kkk/sp
fsk/tt/p
4.-regex使用正则表达式查找
-regex同样属于测试项。使用-regex时有一点要注意:-regex不是匹配文件名,而是匹配完整路径名,也就是说包括目录。
例如,当前目录下有一个文件"abar9"
,如果你用"ab.*9"
来匹配,将查找不到任何结果,正确的方法是使用".*ab.*9"
或者".*/ab.*9"
来匹配。
find . -regex '.*/[0-9]*\.[a-z]*'
查找当前目录下文件名为纯数字带后缀,或者直接是后缀的文件
5.-prune排除某个目录
-prune是一个动作项,它表示当文件是一个目录文件时,不进入此目录进行搜索。
要理解-prune动作,首先得理解find命令的搜索规则(也可以说find命令的算法)。
find命令递归遍历所指定的目录树,针对每个文件依次执行find命令中的表达式,表达式首先根据逻辑运算符进行结合,然后依次从左至右对表达式求值。以下面代码为例,进行说明
find PATHP1 OPT1 TEST1 ACT1 ( TEST2 -or TEST3 ) ACT2
(1) 根据OPT1设置项进行find命令的整体设置,若没有-depth设置项,依次进行下面的步骤
(2) 令文件变量File = PATHP1
(3) 对File文件进行TEST1测试,若执行结果为false,转(8)
(4) 对File文件进行ACT1动作,若执行结果为false,转(8)
(5) 对File文件进行TEST2测试,若执行结果为true,转(7)
(6) 对File文件进行TEST3测试,若执行结果为false,转(8)
(7) 对File文件进行ACT2动作
(8) 若File文件是一个目录,并且没有被执行过-prune动作,则进入此目录
(9) 当前目录下是否还有文件,若有依次取一个文件,令File指向此文件,转(3);
(10) 判断当前目录是否是PATHP1,若是则程序退出;若不是,则返回上一层目录,转(9)
-prune经常和-path一起使用,以避开某个目录,常见的形式是:
find PATH -path <dont want> -prune -o -path <want>
find . -path "./sk" -prune -o -name "*.txt" -print
查找当前目录或者子目录下所有.txt文件,但是跳过子目录sk
注意:如果同时使用-depth设置项,那么-prune将被find命令忽略。man手册页中这么说:“If -depth is given, false; no effect.”
6.时间 指定时间查找
时间有三种:文件访问时间(以a开头)、文件状态修改时间(以c开头)、文件内容修改时间(以m开头)
两组时间选项
-amin, -cmin, -mmin,单位是分钟
-atime, -ctime, -mtime,单位是天
“-amin n"和”-atime n"的处理方法都是:根据当前时间和文件的相应时间属性求差值,然后比较差值和参数n,看是否符合要求。但是这个求差值的过程却有很大不同,他们的不同也代表了两组(基于分钟和基于天)的不同:
"-amin n"
(1)求Δt,用当前时间减去文件时间值即得到Δt,Δt = tnow - tfile;
(2)求浮点数f,用Δt除以1分钟,f = Δt / 1min;
(3)将f的小数部分入到整数部分,得到差。即,不管f是6.0102还是6.8901,差值都等于7
"-atime n"
(1)求Δt,用当前时间减去文件时间值即得到Δt,Δt = tnow - tfile;
(2)求浮点数f,用Δt处以24小时,f = Δt / 24hours;
(3)将f的小数部分都舍掉,得到差。即,不管f是6.0102还是6.8901,差都等于6
-amin +3 +3表示差值大于3
-amin -3 -3表示差值小于3
-amin 3 表示差值等于3
find . -type f -atime -7
搜索最近七天内被访问过的所有文件
find . -type f -atime 7
搜索恰好在七天前被访问过的所有文件
find . -type f -atime +7
搜索超过七天被访问过的所有文件
find . -type f -amin +10
搜索访问时间超过10分钟的所有文件
-anewer file
-cnewer file
-newer file
find . -type f -newer file.log
找出比file.log内容修改时间更晚的所有文件
7.-perm指定权限查找
-perm支持符号权限位表示法也支持绝对(八进制)权限位表示法
-perm基本上有下面这几种形式
-perm mode 文件的权限位恰好是 mode (八进制或符号)
-perm -mode All of the permission bits mode are set for the file.
-perm +mode Any of the permission bits mode are set for the file.
find . -type f -perm 777
当前目录下搜索出权限为777的文件
find . -type f -name "*.php" ! -perm 644
找出当前目录下权限不是644的php文件
8.-type 指定文件类型查找
-type 类型,支持如下类型:
b block (buffered) special
c character (unbuffered) special
d directory
p named pipe (FIFO)
f regular file
l symbolic link;
s socket
D door (Solaris)
find . -name "e100*" -type l
查找当前目录下文件名为e100开头的链接文件
9.-size 指定文件大小查找
-size测试项根据文件的大小查找文件,-size [±]n单位,单位有:[cwbkMG],分别表示
‘b’ for 512-byte blocks (this is the default if no suffix is used)
‘c’ for bytes
‘w’ for two-byte words
‘k’ for Kilobytes (units of 1024 bytes)
‘M’ for Megabytes (units of 1048576 bytes)
‘G’ for Gigabytes (units of 1073741824 bytes)
+表示大于
-表示小于
没有表示等于
find . -type f -size +10k
搜索大于10KB的文件
find . -type f -size -10m
搜索小于10MB的文件
find . -type f -size 10g
搜索等于10GB的文件
10.根据用户、用户组来查找文件
-uid n
-user username or uid
-nouser
-gid n
-group gname or gid
-nogroup
find . -type f -user tom
找出当前目录用户tom拥有的所有文件
find . -type f -group sunk
找出当前目录用户组sunk拥有的所有文件
11.深度控制
find . -maxdepth 3 -type f
向下最大深度限制为3
find . -mindepth 2 -type f
搜索出深度距离当前目录至少2个子目录的所有文件
12.列出所有大小为零的文件
find . -empty
13.-delete 删除找到的文件
find . -type f -name "*.txt" -delete
删除当前目录下所有.txt文件
14.-exec 执行外部命令
对查找到的文件可以调用外部命令处理。-exec动作项就是来完成这个功能的,格式是:
find . EXPR1 -exec command {} \;
注意:后一个花括号'}'和'\'之间有一个空格,最后以分号;结尾,因为各个系统中分号会有不同的意义,所以前面加反斜杠。
{} 花括号代表前面find查找出来的文件名。
find . -type f -exec ls -l {} \;
查找当前目录下的所有普通文件,并用ls命令输出
find .-type f -user root -exec chown tom {} \;
找出当前目录下所有root的文件,并把所有者更改为用户tom
find . -type f -name "*.txt" -exec cat {} \;> all.txt
查找当前目录下所有.txt文件并把他们拼接起来写入到all.txt文件中
find . -type f -mtime +30 -name "*.log" -exec cp {} old \;
将30天前的.log文件移动到old目录中
find . -type f -name "*.txt" -exec printf "File: %s\n" {} \;
找出当前目录下所有.txt文件并以“File:文件名”的形式打印出来
因为单行命令中-exec参数中无法使用多个命令,使用脚本可以实现在-exec之后接受多条命令
-exec ./text.sh {} \;
15.-ok
find $HOME/. -name "*.txt" -ok rm {} \;
找出自己家目录下所有的.txt文件并删除
-ok和-exec一样,不过它会给出提示,是否执行相应的操作。
16.-print0
表示find输出的每条结果后面加上 '\0' 也就是null,而不是换行。
find /path -type f -print0 | xargs -0 rm
上面命令删除/path路径下的所有文件。由于分隔符是null,所以处理包含空格的文件名,也不会报错。