find -文件搜索
find - search for files in a directory hierarchy(在目录层次结构中搜索文件)
强大的文件搜索命令,可以根据文件的属性来查找,比如,时间范围,文件大小,文件权限,文件类型等方法进行搜索,并且还可与
xargs
命令对搜索出的文件进行更深一步的操作。
格式:
find [path...] [expr...] [expression]
path:
path
就是想要搜索的目录,如不写默认当前目录,也可填写多个目录,则表示在多个目录下搜索。默认搜索会递归搜索目录下的所有文件,如果需要控制目录层级,可以使用参数-maxdepth level
来控制递归的目录层级。
[root@node1 ~]# find /var/log/ -maxdepth 1 -size +400k #目录递归层级为1且文件大小大于400K的文件
/var/log/messages-20190113
###expr: ####一、与时间有关的选项:共有-atime,-mtime和-ctime,下面以-mtime说明 * -mtime [+-]n :n为天数,(+)在n天前,(-)在n天内。无符号表示在n天前的那一天 * -newer file :列出比file还要新的文件,比较的是mtime的时间
[root@node1 tmp]# find /tmp/ -mtime 0 #0表示目前时间,也就是从现在到24小时前
/tmp/
/tmp/d
[root@node1 tmp]# ll /tmp/
-rwxr--r-- 1 root root 9 Feb 11 22:50 a
-------r-- 1 root root 9 Feb 11 22:50 b
lrwxrwxrwx 1 root root 1 Feb 18 21:25 d -> a
[root@node1 tmp]# touch -m -t 201902182124.30 a #修改时间
[root@node1 tmp]# ll
-rwxr--r-- 1 root root 9 Feb 18 21:24 a
-------r-- 1 root root 9 Feb 11 22:50 b
lrwxrwxrwx 1 root root 1 Feb 18 21:25 d -> a
[root@node1 tmp]# find /tmp/ -newer a #搜索比文件a更新的文件
/tmp/
/tmp/d
二、与文件权限及名称有关的参数
- -name filename:按文件名查找文件
- -iname filename:按文件名查找文件,但忽略大小写
- -size [+-]size:根据文件的大小进行查找。(+)表示大于指定大小(-)表示小于指定大小,无符号表示等于指定大小。后缀单位有
c
表示bytes,k
表示kilobytes,M
表示Megabytes,G
表示Gigabytes - -type TYPE:根据文件的类型进行查找。TYPE类型有:
f
标准文件,d
目录,c
字符设备,b
块设备,l
链接,p
管道,s
socket等属性 - -perm [-]mode :根据文件权限进行查找。(-)表示必须囊括mode的权限,(+)被废弃了。
[root@node1 tmp]# find /tmp/ -size 9c #等于9个字节大小的文件
/tmp/b
/tmp/a
[root@node1 tmp]# find /var/log/ -size +400k #大于400K的文件
/var/log/audit/audit.log
[root@node1 tmp]# find /tmp/ -type f #文件类型为f的文件
/tmp/b
/tmp/a
[root@node1 tmp]# find / -maxdepth 1 -type d #文件类型为目录
/
/boot
/dev
/proc
/run
/sys
/etc
/root
/var
/tmp
/usr
/home
/media
/mnt
/opt
[root@node1 tmp]# ll
total 8
-rwxr--r-- 1 root root 9 Feb 11 22:50 a
-------r-- 1 root root 9 Feb 11 22:50 b
lrwxrwxrwx 1 root root 1 Feb 18 21:25 d -> a
drw-r----- 2 root root 24 Feb 11 21:49 dai
[root@node1 tmp]# find /tmp/ -perm 744 #匹配指定权限
/tmp/a
[root@node1 tmp]# find /tmp/ -perm -004 -maxdepth 1 #other权限至少有读权限才能匹配到
/tmp/
/tmp/b
/tmp/d
/tmp/a
[root@node1 tmp]#
三、与属主或属组名称有关的参数
- -user :根据文件属主查找,即可填用户名也可填uid
- -group :根据文件属组查找,即可填属组名也可填gid
- -nouser :寻找文件的属主不存在于/etc/passwd中
- -nogroup :寻找文件的属组不存在于/etc/group
[root@node1 tmp]# ll /tmp/a
-rwxr--r-- 1 jerry root 9 Feb 18 21:24 /tmp/a
[root@node1 tmp]# find /tmp/ -user jerry -group root
/tmp/a
[root@node1 tmp]# userdel jerry
[root@node1 tmp]# userdel jerry
userdel: user 'jerry' does not exist
[root@node1 tmp]# find /tmp/ -nouser
/tmp/a
####四、与文件inode有关的参数 * -inum :根据文件的索引节点号查找。 * -samefile name :文件引用与名称相同的inode,当使用-L选项时,软链接也包括软链接。
[root@node1 tmp]# stat --printf=%i a #显示a文件的inode
17293314
[root@node1 tmp]# find -inum 17293314 #搜索当前目录下inode为17293314的文件
./a
[root@node1 tmp]# cp -l a c #创建硬链接
[root@node1 tmp]# ll
total 12
-rw-r--r-- 2 root root 9 Feb 11 22:50 a
-rw-r--r-- 1 root root 9 Feb 11 22:50 b
-rw-r--r-- 2 root root 9 Feb 11 22:50 c
[root@node1 tmp]# find /tmp/ -samefile a #查找出相同inode的文件
/tmp/a
/tmp/c
[root@node1 tmp]# cp -s a d
[root@node1 tmp]# ll
total 12
-rw-r--r-- 2 root root 9 Feb 11 22:50 a
-rw-r--r-- 1 root root 9 Feb 11 22:50 b
-rw-r--r-- 2 root root 9 Feb 11 22:50 c
lrwxrwxrwx 1 root root 1 Feb 18 21:25 d -> a
[root@node1 tmp]# find /tmp/ -samefile a
/tmp/a
/tmp/c
[root@node1 tmp]# find -L /tmp/ -samefile a #当使用-L时,目录下的软链接可以搜索出源文件的属性
/tmp/a
/tmp/c
/tmp/d
[root@node1 tmp]# find -inum 17293314 -exec mv {} /tmp/aa \; #一般inum用来将乱码的文件进行删除或重命令名操作
[root@node1 tmp]# ll
-rw-r--r-- 1 root root 9 Feb 11 22:50 aa
-rw-r--r-- 1 root root 9 Feb 11 22:50 b
lrwxrwxrwx 1 root root 1 Feb 18 21:25 d -> a
五、额外常用的选项
- -prune :查找指定目录时,可指定忽略其中的一个或几个目录
- -depth :find命令默认是深度查找,即搜索到指定目录下的目录时,会一直将上目录搜索结束,在返回上一层继续搜索。而depth是先一层层的搜索,也叫广度搜索。效果是在特定使用场景下减轻搜索压力。
[root@node1 tmp]# find /tmp/ -size 9c -print #搜索/tmp目录下文件大小为9字节的文件
/tmp/dai/index.html
/tmp/b
/tmp/a
[root@node1 tmp]# find /tmp/ -path /tmp/dai -prune -o -size 9c -print #搜索但不包括/tmp/dai目录下的文件
/tmp/b
/tmp/a
这里示例是-print
显示出来。其实忽略目录其实可以与grep -v
结合也可以简单的实现
[root@node1 tmp]# find /tmp/ -size 9c | grep -v "/tmp/dai"
/tmp/b
/tmp/a
六、operators
- ( expr ) :优先判断,通常在shell中需要转义(...)
- ! expr :如果expr为假,则为真
- expr1 expr2 :一行中的两个表达式被认为与隐含的"and"或"-a"连接;如果expr1为假,则不计算expr2。
- expr1 -o expr2 :一行中的两个表达式被认为与隐含的"or"连接;如果expr1为真,则不计算expr2。
-o
和-a
相当于shell中的||
和&&
,可以组成多种判断条件。
[root@node1 dai]# ll
total 4
-rw-r--r-- 1 root root 9 Feb 19 01:20 index.html
-rw-r--r-- 1 root root 0 Feb 19 20:09 index.pdf
-rw-r--r-- 1 root root 0 Feb 19 20:04 index.txt
[root@node1 dai]# find ./ -perm 644 -name "*.txt" #默认两个expr使用-a相连,匹配两个条件都满足的文件
./index.txt
[root@node1 dai]# find ./ \( -name "*.html" -o -name "*.pdf" \) #匹配以html结尾的文件和以pdf结尾的文件
./index.html
./index.pdf
[root@node1 dai]# find ./ ! \( -name "*.html" -o -name "*.pdf" \) #取反
./
./index.txt
[root@node1 dai]# find ./ -name "*.html" -name "*.pdf" #匹配两个条件都满足,则为空
[root@node1 dai]#
expression
额外进行的动作
- -print :默认输出动作,可不写
- -exec command :command为其它命令,-exec后面可再接额外的命令来处理搜寻到的结果
- -ok command {} ; :交互式要求用户确认执行命令
[root@node1 tmp]# find /tmp/ -size 0c #搜索大小为空的文件
/tmp/x
[root@node1 tmp]# find /tmp/ -size 0c -exec ls -l {} \;
-rw-r--r-- 1 root root 0 Feb 19 01:37 /tmp/x
[root@node1 tmp]#
- {} 代表的是由find搜索到的文件,如上示例所示,/tmp/x就个目标文件就会放置到{}中
- -exec ... ; 是关键字,代表find额外动作的范围。
- ; 在bash环境下是连续指令的意思,因此要用反斜线转义。
在使用find命令的-exec选项处理匹配到的文件时,find命令会将所有匹配到的文件一起传递给exec执行。但有些系统能对能够传递给exec的命令长度有限制,这样在find命令运行几分钟后,就会出现溢出错误。错误信息通常是“参数太长”或“参数列溢出”。解决这种问题,就需要和xargs命令。
find命令把匹配到的文件通过管道符|传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,可根据参数进行调整每批次的数量。然后一批一批的处理。
xargs
xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换为特定命令的命令参数。xargs也可以将单选或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。xargs是构建单行命令的重要组件之一。
option:
- -n num :指定每行显示的字段数
- -p:操作具有可交互性,每次执行command都交互提示用户选择,当每次执行一个argument的时候询问一次用户
- -i or -I :将xargs的每项名称,一般是一行一行赋值给{},可以用{}代替,注意,-I必须指定替换字符 -i 是否指定替换字符-可选
- -r :如果没有要处理的参数传递给xargs默认是带空参数运行一次,如果你希望无参数时,停止xargs,直接退出,使用-r选项即可,其可以防止xargs后面命令带空参数运行报错。
[root@node1 tmp]# find /tmp/ -size 0c | xargs -n 2 #第次只接收两个参数
/tmp/mongodb-27017.sock /tmp/x
/tmp/access.log /tmp/error.log
[root@node1 tmp]# find /etc/nginx/ -name "*.conf" | xargs -i cp -a {} {}_bak #对配置文件进行备份
[root@node1 tmp]# find /tmp/ -name sdadfdf | xargs tar zcvf 1.tar.gz #查找一个没有的文件,并对其进行重命令
tar: Cowardly refusing to create an empty archive
Try `tar --help' or `tar --usage' for more information.
[root@node1 tmp]# find /tmp/ -name sdadfdf | xargs -r tar zcvf 1.tar.gz #没有参数时,不会报错,不运行
[root@node1 tmp]#
**生产中常用示例:**
- 将七天前的日志备份压缩
find /app/nginx/logs/ -mtime +7 -name "*.log" | xargs tar zcf nginx_log_`date +%F`.tar.gz
- 备份重要配置文件
mkdir -p /backup/`date +%F`;find /app/nginx -name "*.conf" | xargs -i cp -a {} /backup/`date +%F`/{}
- 删除乱码文件,前提是知道此文件的inode号,可通过ll -i查看
find /xxx -inum xxxx -exec rm -f {} \;
**总结:** `find`命令是一个非常强大的文本搜索工具,可以根据文件的相关属性搜索并配合`xargs`命令使用可以使用户对所匹配到的文件执行几乎所有的命令。但是`find`命令是实时搜索,如果搜索范围过大,将会消耗过多的系统性能。但不是经常用,也就可以忽略了。