引入
Linux find命令非常强大,之前因为用得少,一直没有太系统梳理过,最近因为出了一个inode过高预警,要分析目录和文件才重新整理。
发现,如果熟悉find命令,很多操作处理起来可以更加灵活、得心应手。
我把参数说明放在最后,从我遇到的一个实际问题开始来说明。
我们有一块NAS盘,一直告警文件系统使用inode索引节点大于85%,一看磁盘空间实际使用占比却不高。
通常,这种情况出现的原因基本可以确定,是大量小文件或者空目录,占用了大量的索引空间,但实际并没有存储多少数据。
所以,目标就非常明确了,就是查找空目录、和文件小于指定值的小文件。
先统计一下目录下小于1KB和空目录文件数量:
find -size -1k -o -empty | wc -l
发现有130多万个,进一步分析这其中,绝大部分是空目录。
为了安全先删除空目录:
# 文件太多,-exec肯定不行,要溢出
find ./ -type d -empty | -exec rm {} \;
# 使用-delete操作
find ./ -type d -empty -delete
常用动作
find默认查找当前目录、会递归查找子目录
操作 | 说明 |
---|---|
-delete | 删除 |
-ok command {} ; | 使用find结果作为参数执行命令,会每次执行进行询问操作,需要用户确认 |
-exec command {} ; | 使用find结果作为参数执行命令,不询问 |
默认、文件全路径输出到控制台、fprint可以输出到文件 | |
-ls | 列举文件 |
更多详情可以通过man find查看。
find ./ -type f -print
# 查找最后修改时间在15天以前的log文件并删除它们,需要确认
find ./ -name "*.log" -mtime +15 -ok rm {} \;
# maxdepth 1为只在当前目录找,2是当前目录和下一级目录找,注意;前的反斜杠不能少
find . -maxdepth 2 -iname "*oss*" -exec ls -d {} \;
xargs
-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给-exec执行,系统传递给-exec的命令长度有限制,如果find的结果比较多,可能会出现溢出错误。(参数列太长、参数列溢出)
这种情况就可以使用xargs命令,find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,它会先处理最先获取的一部分文件,然后处理下一批,直到全部处理完成。
另外,在部分系统中-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,可能导致进程过多,xargs命令则只有一个进程。
# 查找所有用户具有读、写和执行权限的文件,并收回相应的写权限
# r:4 w:2 x:1, 所以777就代表 rwxrwxrwx
find ./ -perm -777 -print | xargs chmod o-w
# 在当前目录中所有文件中grep hostname
find ./ -type f -print | xargs grep "hostname"
# 将当前目录及其子目录中所有后缀为".log"的文件移动到/tmp目录下面
# {} 花括号代表前面find查找出来的文件名
find ./ -name "*.log" | xargs -i mv {} /tmp
根据文件名字查找-name
- -name:按照文件名搜索
- -iname:按照文件名搜索,不区分文件名大小写
- -inum:按照inode索引搜索
# 列出当前目录及其子目录下所有文件后缀为[.log]的文件
find ./ -name "*.log"
# 查找当前目录下以大写字母开头的文件
find . -name "[A-Z]*"
# 查找/var/log/report目录下以sys-开头的文件
find /var/log/report -name "sys-*"
# 查询当前目录下以大写字母开头+8个数字的.csv文件
find . -name "[A-Z][0-9]{8}.csv"
根据文件类型查找-type
符号 | 文件类型 |
---|---|
b | 块设备文件 |
d | 目录 |
c | 字符设备文件 |
p | 管道文件 |
l | 符号链接文件 |
f | 普通文件 |
# 列出当前目录及其子目录中的所有文件
find ./ -type f
find ./ -type d
find ./ -type d | sort
# 在~/bin目录下查找所有的符号链接文件
find ~/bin -type l
根据文件大小查找-size
符号 | 说明 |
---|---|
c | 字节、默认 |
b | 文件块、默认512字节 |
w | 2字节 |
k | 1024字节、1KB |
M | 1048576字节、1MB、1024KB |
G | 1073741824字节、1GB、1024MB |
- +表示大于,如:+2k表示大于2KB的文件
- -表示小于,如:-10M表示小于10MB的文件
# 查找当前目录下文件大小为2048(2k)字节的文件,下面3个等价
find ./ -size 2048
find ./ -size 2048c
find ./ -size 2K
# 查找大于1024字节的文件,下面2个等价
find ./ -size +1024c
find ./ -size +1k
# 查找小于1024字节的文件
find ./ -size -1024c
# 查找/var/log目录下大于100k且小于400k的文件并列出它们的完整路径
find /var/log -type f -size +100k -size -400k | xargs ls –l
# 基本和上一个等价
find /var/log -type f -size +100k -size -400k -exec ls -l {} \;
根据时间查找
- mtime:最后修改时间,modification time(mtime):当修改文件的内容数据的时候,就会更新这个时间
- ctime:状态修改时间,当修改文件的权限或者属性的时候,就会更新这个时间,最开始的就是创建时间
- atime:最后访问时间,access time(atime),当使用这个文件的时候就会更新这个时间
注意:ctime不是创建时间,而是文件属性(状态)修改时间
上面3个默认的时间单位是天,下面3个默认时间单位是分钟
-
amin
-
cmin
-
mmin
-
-n 表示n天(分钟)以内
-
+n 表示n天(分钟)以前
# 查找最后修改时间10天以前的文件
find ./ -mtime +10
# 查找10分钟内访问过的文件
find . -amin -10
# 查找更改时间比文件oss.csv新但比文件report.csv旧的文件
find . -newer oss.csv ! -newer report.csv
# 查找更改时间在比oss.csv文件新的文件
find . -newer oss.csv
逻辑运算符
- -a and
- -o or
- -not not(!)
# 查找当前目录下大于2KB,并且文件类型是普通文件的文件
find . -size +2k -a -type f
# 查找当前目录下oss和app文件
find . -name oss -o -name app
# 查找当前目录非日志文件
find . -not -name *.log
find . ! -name *.log
综合实例
# 根据文件权限为查找,查找当前目录及其子目录中所有权限为777的目录或者文件
find ./ -perm 777
# 删除当前文件夹下的所有空文件夹
find ./ -type d -empty -delete
find ./ -type d -empty | xargs rm -rf
# 查找当期目录下名字包含"oss"字符(不去分大小写)的目录或文件,并通过命令ls -d 显示出来。
find . -maxdepth 1 -iname "*oss*" -exec ls -d {} \;
# 删除/tmp目录下大于100MB的文件
find /tmp –size +100M | xargs 'rm –rf '
find ./ -type f -perm 644 -exec ls -l {} \;
# 查找当前目录中文件属主具有读、写权限,并且文件所属组的用户和其他用户具有读权限的文件
find ./ -type f -perm 644 -exec ls -l {} \;
# 查找系统中所有文件长度为 0 的普通文件,并列出它们的完整路径
find / -type f -size 0 -exec ls -l {} \;
# 将command命令放在find命令的-exec选项中执行
find ./ -type f -exec ls -l {} \;
# 在目录中查找后缀为**.log**的文件且更改时间在14日以前的文件并删除它们,在删除之前先给出提示
find ./ -name "*.log" -mtime +14 -ok rm {} \;
# grep money当前目录下所有以app开头的文件
find ./ -name "app*" -exec grep "money" {} \;
find ./ -name "app*"|xargs grep money
# 查找文件并移动到指定目录,将当前目录及其子目录中所有后缀为".log"的文件移动到/tmp目录下面
find ./ -name "*.log" -exec mv {} /tmp \;
find ./ -name "*.log" -exec cp {} /tmp \;
# 查找更改时间在14天以前的文件并删除它们
find ./ -type f -mtime +14 -exec rm {} \;
# 查找/var/log/report目录中更改时间在7天以前的普通文件,并删除(询问模式)
find /var/log/report -type f -mtime +7 -ok rm {} \;
# 查找文件排查bin目录
find . -path "./bin" -prune -o -name *.csv -print
# 先输出子目录,再输出上层目录内容
find . -depth ! -empty
# 先输出顶层目录,再输出下面的各层子目录内容
find . ! -empty
参数与说明
常用参数说明:
参数 | 说明 |
---|---|
-name | 按照文件名查找文件 |
-size n[cwbkMG] | 按大小查找 |
-type | 查找某一类型的文件 |
-perm | 按照文件权限来查找文件 |
-amin n | 最后访问时间n分钟以内(以前) |
-cmin n | 最后修改属性时间n分钟以内(以前) |
-mmin n | 最后修改时间n分钟以内(以前) |
-atime n | 最后访问时间n天以内(以前) |
-ctime n | 后修改属性时间n天以内(以前) |
-mtime n | 最后修改时间n天以内(以前) |
-maxdepth | 最大层级数 |
其他参数说明:
参数 | 说明 |
---|---|
-anewer file | 比文件file更晚被读取过的文件 |
-cnewer file | 比文件file更新的文件 |
-newer file1 ! file2 | 查找更改时间比文件file1新但比文件file2旧的文件 |
-empty | 空的文件 |
-ipath p, -path p | 路径名称符合p的文件,ipath会忽略大小写 |
-user | 按照文件属主来查找文件 |
-group name | 按照文件所属的组来查找文件 |
-gid n | 按group ID查找 |
-nogroup | 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在 |
-nouser | 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在 |
-mindepth | 最小层级数 |
-depth | 在处理目录以前首先处理目录下的子内容 |
-fstype | 指定文件系统类型(/etc/fstab配置) |
-mount | 在查找文件时不跨越文件系统mount点,只检查和指定目录在同一个文件系统下的文件,避免列出其它文件系统中的文件 |
-prune | 排除指定目录,如果同时使用-depth选项,那么-prune将被find命令忽略 |
-follow | 如果find命令遇到符号链接文件,就跟踪至链接所指向的文件 |
-cpio | 对匹配的文件使用cpio命令,将这些文件备份到磁带设备中 |