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管道,ssocket等属性
  • -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]# 

**生产中常用示例:**
  1. 将七天前的日志备份压缩
find /app/nginx/logs/ -mtime +7 -name "*.log" | xargs tar zcf nginx_log_`date +%F`.tar.gz 
  1. 备份重要配置文件
mkdir -p /backup/`date +%F`;find /app/nginx -name "*.conf" | xargs -i cp -a {} /backup/`date +%F`/{}
  1. 删除乱码文件,前提是知道此文件的inode号,可通过ll -i查看
find /xxx -inum xxxx -exec rm -f {} \;

**总结:** `find`命令是一个非常强大的文本搜索工具,可以根据文件的相关属性搜索并配合`xargs`命令使用可以使用户对所匹配到的文件执行几乎所有的命令。但是`find`命令是实时搜索,如果搜索范围过大,将会消耗过多的系统性能。但不是经常用,也就可以忽略了。
posted @ 2019-02-19 17:43  dance_man  阅读(253)  评论(0)    收藏  举报