linux之find命令详解
⼀、find概述
话不多说,先来find --help⼀下
[hive@lgh test]$ find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [] [expression] #使⽤的语法
default path is the current directory; default expression is -print #默认是当前⽬录,默认采⽤的action是-print,如果有设置action,则默认会被覆盖
expression may consist of: operators, options, tests, and actions:
operators (decreasing precedence; -and is implicit where no others are given): #⼀些重要操作,就像编程⾥⾯所⽤到的,与,⾮,或这些关系,
( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2
EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2
positional options (always true): -daystart -follow -regextype #总是返回true
normal options (always true, specified before other expressions): #总是返回true
-depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf
--version -xdev -ignore_readdir_race -noignore_readdir_race
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N #重点
-cnewer FILE -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]
-context CONTEXT
actions: -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 ;
Report (and track progress on fixing) bugs via the findutils bug-reporting
page at / or, if you have no web access, by sending
email to <>.
从上看:find命令的使⽤语法:
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [] [expression]
其中expression主要包括operators, options, tests, and actions
expression may consist of: operators, options, tests, and actions:
⼆、find基本原理和实践
find是从左向右处理的,所以表达式的前后顺序不同会造成不同的搜索性能差距。
搜索机制:find的搜索机制是根据表达式返回的true/false决定的,每搜索⼀次都判断⼀次是否能确定最终评估结果为true,只有评估的最终结果为true才算是到。
find⾸先对整个命令⾏进⾏语法解析,并应⽤给定的options,然后定位到搜索路径path下开始对路径下的⽂件或⼦⽬录进⾏表达式评估或测试,评估或测试的过程是按照表达式的顺序从左向右进⾏的(此处不考虑操作符的影响),如果最终表达式的表达式评估为true,则输出(默认)该⽂件的全路径名
2.1、操作符(operators)
我相信⼤家都学过⼀些编程语⾔,这⾥的运算操作符合java中的编程语⾔⼀样的意思,其实就是⼀些
与,或,⾮的操作,都是⼀些短路的操作,虽然⽐较简单,但是很有⽤,接下来我们具体看下这些内容:
(expr) #优先级最⾼。为防⽌括号被shell解释(进⼊⼦shell),所以需要转义,即\(...\)
! expr #对expr的true和false结果取反。同样需要使⽤引号包围
-not expr #等价于"! expr"
expr1 expr2 #等同于and操作符。
expr1 -a expr2 #等同于and操作符。
expr1 -and expr2 #⾸先要求expr1为true,然后expr2以expr1搜索的结果为基础继续检测,然后再返回检测值为true的⽂件。因为expr2是以expr1结果为基础的,所以如果expr1返回
#false,则expr2直接被忽略⽽不会进⾏任何操作
expr1 -o expr2 #等同于or操作符
expr1 -or expr2 #只有expr1为假时才评估expr2。
expr1 , expr2 #逗号操作符表⽰列表的意思,expr1和expr2都会被评估,但expr1的true或false是被⽆视的,只有expr2的结果才是最终状态值。
[hive@lgh test]$ ll
total 8
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find . -type f -a -name c #打印⽂件,并且名为c
./c
[hive@lgh test]$ find . -type f -o -type d #打印⽂件或者⽬录
.
./a
./b
./c
注意:and 的优先级⾼于 or,and和or操作都是短路操作,先判断第⼀个条件,and:如果第⼆个条件不满⾜,则第⼆个条件不予判读,or则相反
2.2、选项(options)
options总是返回true。除了"-daystart",options会影响所有指定的test表达式部分,哪怕是test部分写在options的前⾯。这是因为options是在命令⾏被解析完后⽴即处理的,⽽test是在检测到⽂件后才处理的。对于"-daystart"这个选项,它们仅仅影响写在它们后⾯的test部分,因此,建议将任何options部分写在expression的最前⾯。
-daystart #指定以每天的开始(凌晨零点)计算关于天的时间,⽤于改变时间类(-amin,-atime,-cmin,-ctime,-mmin和-mtime)
#的计算⽅式。默认天的计算是从24⼩时前计算的。例如,当前时间为5⽉3⽇17:00,要求搜索出2天内修改过的⽂件,默认
#搜索⽂件的起点是5⽉1⽇17:00,如果使⽤-daystart,则搜索⽂件的起点是是5⽉1⽇00:00。
#注意,该选项只会影响写在它后⾯的test表达式。
-depth #搜索到⽬录时,先处理⽬录中的⽂件(⼦⽬录),再处理⽬录本⾝。对于"-delete"这个action,它隐含"-depth"选项。
-maxdepth levels #指定tests和actions作⽤的最⼤⽬录深度,只能为⾮负整数。可以简单理解为⽬录搜索深度,但并⾮如此。当
#前path⽬录的层次为1,所以若指定-maxdepth 0将得不到任何结果。
-mindepth levels #tests和actions不会应⽤于⼩于指定深度的⽬录,"-mindepth 1"表⽰应⽤于所有的⽂件。
-ignore_readdir_race #当⽆法⽤stat检测⽂件信息时(如⽆权限)会给出下图所⽰的错误信息,如要忽略该信息,可以使⽤该选项。
[root@lgh ~]# find /etc -name passwd
find查命令的使用/etc/passwd
/etc/pam.d/passwd
[root@lgh ~]# find /etc -maxdepth 1 -name passwd
/etc/passwd
[root@lgh ~]#
[root@lgh ~]# find /etc -maxdepth 2 -mindepth 2 -name passwd #之返回第⼆层⽬录的匹配⽂件
/etc/pam.d/passwd
如果指定了-depth,则先处理⽬录中的⽂件,再处理⽬录本⾝。在Linux⼀切皆⽂件,⼦⽬录也是⽂件
[hive@lgh test]$ ll
total 8
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 1.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 2.bak
-
rw-rw-r-- 1 hive hive 0 Sep 30 10:52 3.bak
drwxrwxr-x 2 hive hive 4096 Sep 30 10:52 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find ../test -depth
../test/3.bak
../test/
../test/
../test/
../test/a #先处理⽬录a下的⽂件,才处理a⽬录
.
./test/1.bak
../test/b
../test/2.bak
../test/c
../test/d
../test #最后才处理⽬录
2.3、tests
(N can be +N or -N or N)
+n:⼤于n
-n:⼩于n
n :精确的等于n
2.3.1、从⽂件类型判断
-type [bcdpflsD]
X #根据⽂件类型来搜索
b #块设备⽂件
c #字符设备⽂件
d #⽬录
p #命名管道⽂件(FIFO⽂件)
f #普通⽂件
l #符号链接⽂件,即软链接⽂件
s #套接字⽂件(socket)
[hive@lgh test]$ ll
total 8
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find . -type l #查链接⽂件
./d
2.3.2、从⽂件⼤⼩判断
-size N[bcwkMG]
b #512字节的(默认单位)
c #1字节的
w #2字节
k #1024字节
M #1024k
G #1024M
empty:空⽂件,对于⽬录来说,则是空⽬录
[hive@lgh test]$ ll
total 8
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find -size 1 #⽂件⼤⼩为1字节
./d
[hive@lgh test]$ find -size -2 #⽂件⼤⼩⼩于2字节
./c
./d
2.3.3、从⽂件名后者路径名判断
-name pattern #⽂件的basename(不包括其前导⽬录的纯⽂件名)能被通配符模式的pattern匹配到。需要注意的是,在find中的通配元字符"*"、"?"和"[]"是能够匹配以点开头的⽂件的
-iname pattern #不区分⼤⼩的"-name"
-path pattern #⽂件名能被通配符模式的pattern匹配到。此模式下,通配元字符"*"、"?"和"[]"不认为字符"/"或"."是特殊字符,也就是说这两个字符也在通配范围内,所以能匹配这两个字符。-ipath pattern #不区分⼤⼩写的"-path"
-
regex pattern #⽂件名能被正则表达式pattern匹配到的⽂件。正则匹配会匹配整个路径,例如要匹配⽂件名为"./fubar3"
#的⽂件,可以使⽤".*bar."或".*b.*3",但不能是"f.*r3",默认find使⽤的正则类型是Emacs正则,但可以使⽤-regextype来改变正则类型
-iregex pattern #不区分⼤⼩写的"-regex"
[hive@lgh test]$ ll
total 8
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 1.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 2.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 3.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
drwxrwxr-x 2 hive hive 4096 Sep 30 10:52 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find . -name "*.bak"
./3.bak
./1.bak
./2.bak
[hive@lgh test]$ find . -path "./a/*.txt"
.
/
./
./
[hive@lgh test]$ find . -regex ".*txt" #正在匹配
./1.txt
./
./
./
./2.txt
./4.txt
./3.txt
2.3.4、从⽂件权限判断
-perm mode #精确匹配给定权限的⽂件。"-perm g=w"将只匹配权限为0020的⽂件。当然,也可以写成三位数字的权限模式
-perm /mode #匹配任意给定权限位的权限,例如"-perm /640"可以匹配出600,040,700,740等等,只要⽂件权限的任意位能
#包含给定权限的任意⼀位就满⾜
-executable #具有可执⾏权限的⽂件。它会考虑acl等的特殊权限,只要是可执⾏就满⾜。它会忽略掉-perm的测试
-readable #具有可读权限的⽂件。它会考虑acl等的特殊权限,只要是可读就满⾜。它会忽略掉-perm的测试
-writable #具有可写权限的⽂件。它会考虑acl等的特殊权限,只要是可写就满⾜。它会忽略掉-perm的测试(不是writeable)
# find . -type f -perm 0777 -print
# find / -type f ! -perm 777
# find / -perm 2644
# find / -perm /u=s
2.3.5、从⽂件所属情况判断
-gid n #gid为n的⽂件
-group gname #组名为gname的⽂件
-uid n #⽂件的所有者的uid为n
-user uname #⽂件的所有者为uname,也可以指定uid
-nogroup #匹配那些所属组为数字格式的gid,且此gid没有对应组名的⽂件
-nouser #匹配那些所有者为数字格式的uid,且此uid没有对应⽤户名的⽂件
# find / -user root -
# find /home -user tecmint
# find /home -group developer
# find /home -user tecmint -iname "*.txt"
2.3.6、从⽂件的时间参数判断
-anewer file:atime⽐mtime更接近现在的⽂件。也就是说,⽂件修改过之后被访问过
-cnewer file:ctime⽐mtime更接近现在的⽂件
-newer file:⽐给定⽂件的mtime更接近现在的⽂件。
-newer[acm]t TIME:atime/ctime/mtime⽐时间戳TIME更新的⽂件
-amin n:⽂件的atime在范围n分钟内被访问过,对这个⽂件运⽤ more、cat等命令。ls、stat命令都不会修改⽂件的访问时间。注意,n可以是(+ -)n,例如-amin +3表⽰在3分钟以前
-cmin n:⽂件的ctime在范围n分钟内被修改过⽂件的状态,通过chmod、chown命令修改⼀次⽂件属性,这个时间就会更新
-mmin n:⽂件的mtime在范围n分钟内被修改过内容,vim/vi修改保存
-atime n:⽂件的atime在范围24*n⼩时内被访问过
-ctime n:⽂件的ctime在范围24*n⼩时内被修改状态
-mtime n:⽂件的mtime在范围24*n⼩时内被修改内容
-used n:最近⼀次ctime改变n天范围内,atime改变过的⽂件,即atime⽐ctime晚n天的⽂件,可以是(+ -)n
# find / -mtime 50
# find / -atime 50
# find / -mtime +50 –mtime -100
# find / -cmin -60
# find / -mmin -60
# find / -amin -60
2.4、actions
actions部分⼀般都是执⾏某些命令,或实现某些功能。这部分是find的command line部分,注意,action是可以写在tests表达式前⾯的,它并不⼀定是在test表达式之后执⾏。
-delete #删除⽂件,如果删除成功则返回true,如果删除失败,将给出错误信息。"-delete"动作隐含"-depth"。
-exec command; #注意有个分号";"结尾,该action是⽤于执⾏给定的命令。如果命令的返回状态码为0则该action返回true。
#command后⾯的所有内容都被当作command的参数,直到分号";"为⽌,其中参数部分使⽤字符串"{}"时,它
#表⽰find到的⽂件名,即在执⾏命令时,"{}"会被逐⼀替换为find到的⽂件名,"{}"可以出现在参数中的
#任何位置,只要出现,它都会被⽂件名替换。
#注意,分号";"需要转义,即"\;",如有需要,可以将"{}"⽤引号包围起来
-ok command ; #类似于-exec,但在执⾏命令前会交互式进⾏询问,如果不同意,则不执⾏命令并返回false,如果同意,则执
#⾏命令,但执⾏的命令是从/dev/null读取输⼊的
-print #总是返回true。这是默认的action,输出搜索到⽂件的全路径名,并尾随换⾏符"\n"。由于在使⽤"-print"时所有的结
#果都有换⾏符,如果直接将结果通过管道传递给管道右边的程序,应该要考虑到这⼀点:⽂件名中有空⽩字符(换⾏符、制表
#符、空格)将会被右边程序误分解,如⽂件""将被认为是ab和c.txt两个⽂件,如不想被此分解影响,可考虑使
#⽤"-print0"替代"-print"将所有换⾏符替换为"\0"
-print0 #总是返回true。输出搜索到⽂件的全路径名,并尾随空字符"\0"。由于尾随的是空字符,所以管道传递给右边的程序,然后
#只需对这个空字符进⾏识别分隔就能保证⽂件名不会因为其中的空⽩字符被误分解
-prune #不进⼊⽬录,所以可⽤于忽略⽬录,但不会忽略普通⽂件。没有给定-depth时,总是返回true,如果给定-depth,则直接
#返回false,所以-delete(隐含了-depth)是不能和-prune⼀起使⽤的
-ls #总是返回true。将到的⽂件以"ls -dils"的格式打印出来,其中⽂件的size部分以KB为单位
[hive@lgh test]$ ll
total 8
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 1.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 2.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:52 3.bak
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
-rw-rw-r-- 1 hive hive 0 Sep 30 10:
drwxrwxr-x 2 hive hive 4096 Sep 30 10:52 a
drwxrwxr-x 2 hive hive 4096 Sep 30 10:06 b
-rw-rw-r-- 1 hive hive 0 Sep 30 10:06 c
lrwxrwxrwx 1 hive hive 1 Sep 30 10:08 d -> a
[hive@lgh test]$ find . -type f -print -name "*.bak" #这⾥有⼀个action -print,则会覆盖末尾默认的-print,所以在-type -f -print会把所有⽂件打印出来,
#然后-name "*.bak"虽然匹配到了⽂件,但是没有了action,所以没有操作显⽰
./3.bak
./1.txt
./
./
./
./1.bak
./2.txt
./4.txt
./2.bak
./3.txt
./c
[hive@lgh test]$ find . -type f -print -name "*.bak" -ls #这个在上⼀种情况对 -name "*.bak"增加action -ls ,所以会把符合条件的ls出来
./3.bak
64356992 0 -rw-rw-r-- 1 hive hive 0 Sep 30 10:52 ./3.bak
./1.txt
./
./
./
./1.bak
64356990 0 -rw-rw-r-- 1 hive hive 0 Sep 30 10:52 ./1.bak
./2.txt
./4.txt
./2.bak
64356991 0 -rw-rw-r-- 1 hive hive 0 Sep 30 10:52 ./2.bak
./3.txt
./c
[hive@lgh test]$ find . -name "*.txt"
./1.txt
./
./
./
./2.txt
./3.txt
[hive@lgh test]$ find . -path "./a" -prune -o -name "*.txt"
./1.txt
./a #被忽略的⽬录也在⾥⾯
./2.txt
.
/3.txt
注意:如果find评估完所有表达式后发现没有action(-prune这个action除外),则在最末尾加上-print作为默认的action。注意,这个默认的action是在评估完所有表达式后加上的。且还需注意,如果只有-prune这个action,它还是会补上-print。
常⽤命令:
find /backup/rman_backup/ -mtime +45 -exec rm -rf {} ; 删除45天前的⽂件,这样的命令⼀般可以⽤来删除⼀些⽇志,或者⼀些临时⽂件
find /tmp -mtime +7-size +1M -exec rm -rf {} ;
find -mtime +7 -nameabc* -exec rm -rf {} ;
find /tmp -mtime +7-size +1M -ok rm -rf {} ;
更多linux⽂章请见:
参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论