Linux基础笔记10 | 文件查找命令 find 详解

find 常用示例

用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录名。如果使用该命令时,不设置任何参数,则 find 命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示

学习参考博文:骏马金龙 (junmajinlong.com)

最基础的打印功能

## 默认省略了打印,默认是换行符分隔打印
[root@vm10 ~]# find /etc -name passwd
/etc/passwd
/etc/pam.d/passwd
[root@vm10 ~]# find /etc -name passwd -print
/etc/passwd
/etc/pam.d/passwd
[root@vm10 ~]#

## 改变默认分隔符为:\0
[root@vm10 ~]# find /etc -name passwd -print0
/etc/passwd/etc/pam.d/passwd[root@vm10 ~]#

文件名搜索

  • -name:对文件的 basename 进行匹配
  • -path:对文件的 dirname+basename 进行匹配
## 使用 -name 进行搜索匹配
[root@vm10 ~]# find /etc -name passwd
/etc/passwd
/etc/pam.d/passwd
[root@vm10 ~]#

## 不能在 -name 中使用/,除非文件名带有/,
[root@vm10 ~]# find /var/log -path  "*/*/lastlog"
/var/log/lastlog
[root@vm10 ~]#

## 通配符的支持
[root@vm10 ~]# find /etc -name "*wd"
/etc/passwd
/etc/pam.d/passwd
/etc/security/opasswd

文件类型搜索

  • 普通文件:f
  • 目录文件:d
  • 链接文件:l
[root@vm10 ~]# find /etc/yum.repos.d/ -type f
/etc/yum.repos.d/CentOS7-Base-163.repo
[root@vm10 ~]# find /home -type d
/home
/home/test
/home/ceshi
[root@vm10 ~]# find /sbin -type l
/sbin
[root@vm10 ~]# find /bin -type l
/bin
[root@vm10 ~]#

根据文件时间戳搜索

  • -atime:访问时间(数据最后被访问的时间)
  • -mtime:修改时间(文件内容被修改的时间)
  • -ctime:状态时间(文件权限、拥有者、属组、链接数发生改变的时间)
## 3天前被修改;3天内被修改;3天前当天被修改
[root@vm10 ~]# find /etc/yum.repos.d/ -mtime +3
/etc/yum.repos.d/CentOS7-Base-163.repo
[root@vm10 ~]# find /etc/yum.repos.d/ -mtime -3
/etc/yum.repos.d/
[root@vm10 ~]# find /etc/yum.repos.d/ -mtime 3
[root@vm10 ~]#

根据文件大小搜索

  • -size
[root@vm10 ~]# find /var/log -type f -size +100k
/var/log/lastlog
/var/log/audit/audit.log
/var/log/anaconda/syslog
/var/log/anaconda/packaging.log
/var/log/anaconda/journal.log
/var/log/dmesg.old
/var/log/messages-20220825
/var/log/messages-20220901
/var/log/messages-20220904
/var/log/messages
/var/log/dmesg
[root@vm10 ~]#

根据权限搜索

  • -perm
## 注意是搜索有这个权限就能匹配到,并不是权限只能等于440 才能被搜索到
[root@vm10 ~]# find /var/log -type f -perm -0440
/var/log/grubby_prune_debug
/var/log/lastlog
/var/log/wtmp
/var/log/tuned/tuned.log
/var/log/firewalld
/var/log/dmesg.old
/var/log/nginx/access.log-20220903
/var/log/nginx/access.log
/var/log/nginx/error.log-20220903
/var/log/nginx/error.log
/var/log/mysqld.log
/var/log/dmesg
[root@vm10 ~]# ll /var/log/dmesg
-rw-r--r-- 1 root root 119018 95 06:56 /var/log/dmesg
[root@vm10 ~]#

搜索空文件

空文件可以是没有任何内容的普通文件,也可以是没有任何内容的目录

  • -empty
[root@vm10 ~]# find /home -type f -empty
/home/test/5.txt
[root@vm10 ~]# find /home -type d -empty
[root@vm10 ~]# find /etc -type d -empty
/etc/pki/ca-trust/source/anchors
/etc/pki/ca-trust/source/blacklist
/etc/pki/tls/private

搜索到文件并删除

[root@vm10 ~]# find /home -type f -empty
/home/test/5.txt
[root@vm10 ~]# find /home -type f -empty -exec rm -rf '{}' \;
[root@vm10 ~]# find /home -type f -empty
[root@vm10 ~]#

搜索指定日期范围内的文件

  • -newermt
[root@vm10 ceshi]# find -type f -newermt 2022-08-01 -a ! -newermt 2022-09-01
./1.sh
[root@vm10 ceshi]#

并行加速搜索

# 没怎么对比出来,使用了xargs的并行功能,后续研究一下
[root@vm10 ceshi]# find / -name "*Find.pm"
/var/lib/docker/overlay2/aa8c2156bd44012efdf9a697a9f31ad8f3ad2d7a2a422ee4a3972df9d44536fb/diff/usr/share/perl/5.30.0/File/Find.pm
/var/lib/docker/overlay2/aa8c2156bd44012efdf9a697a9f31ad8f3ad2d7a2a422ee4a3972df9d44536fb/diff/usr/share/perl/5.30.0/Pod/Find.pm
/usr/share/perl5/File/Find.pm
[root@vm10 ceshi]# ls --hide proc / | xargs -i -P 0 find /{} -type f -name "*Find.pm"
/usr/share/perl5/File/Find.pm
/var/lib/docker/overlay2/aa8c2156bd44012efdf9a697a9f31ad8f3ad2d7a2a422ee4a3972df9d44536fb/diff/usr/share/perl/5.30.0/File/Find.pm
/var/lib/docker/overlay2/aa8c2156bd44012efdf9a697a9f31ad8f3ad2d7a2a422ee4a3972df9d44536fb/diff/usr/share/perl/5.30.0/Pod/Find.pm
[root@vm10 ceshi]#

获取文件绝对路径

如果使用相对路径进行搜索,出来的结果还是相对路径

## 很多种方法
[root@vm10 ceshi]# find  -type f
./ceshi
./1.sh
./2.sh
[root@vm10 ceshi]# find $(pwd) -type f
/home/ceshi/ceshi
/home/ceshi/1.sh
/home/ceshi/2.sh
[root@vm10 ceshi]# find $PWD -type f
/home/ceshi/ceshi
/home/ceshi/1.sh
/home/ceshi/2.sh
[root@vm10 ceshi]# find  -type f -exec readlink -f {} \;
/home/ceshi/ceshi
/home/ceshi/1.sh
/home/ceshi/2.sh
[root@vm10 ceshi]# find ~+ -type f
/home/ceshi/ceshi
/home/ceshi/1.sh
/home/ceshi/2.sh
[root@vm10 ceshi]#

获取部分文件名

[root@vm10 ceshi]# find  -type f
./ceshi
./1.sh
./2.sh
[root@vm10 ceshi]# find  -type f  -printf "%f\n"
ceshi
1.sh
2.sh
[root@vm10 ceshi]#

结果排出目录本身

[root@vm10 home]# find $(pwd) -type d
/home
/home/test
/home/ceshi
[root@vm10 home]# pwd
/home
[root@vm10 home]# find $(pwd) -type d ! -path $(pwd)
/home/test
/home/ceshi
[root@vm10 home]# find $(pwd) -mindepth 1 -type d
/home/test
/home/ceshi
[root@vm10 home]#

find 运行机制详解

非常感谢优秀的大佬带来的学习记录:(访问有时候好慢)

骏马金龙 (junmajinlong.com)

概述

find 用于搜索文件和目录,工具由 findutils 包提供的,这个包还提供了 xargs 命令,可以对搜索的文件进行后续的一个处理。

find 搜索是从磁盘进行指定目录开始扫描,并不是数据库搜索。

理论基础

find 使用方法:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]

  • 对于选项[-H] [-L] [-P] [-D debugopts] 感觉用处不大,可以参考下官方文档说明man find

  • 对于[path] 路径,不指定路径则在当前目录下进行搜索

  • 对于 expression ,分为三种:options、test、action,对于多个表达式,find 是从左向右处理的,表达式的顺序不同会造成不同的搜索结果和性能差距

  • find 首先会对整个命令进行语法解析,并应用给定的 options,然后定位到指定的搜索路径下进行操作,在操作的过程中,按照表达式的先后顺序从左向右进行,如果表达式为 true,则默认输出该文件的路径

expression-operators

operators:控制 options/tests/actions 的运算方式,多个表达式的运算逻辑的改变

操作符优先级由高到低:

  • (expr):优先级最高
  • !expr:结果取反,需要引号包围
  • -not expr :等价于“!expr”
  • expr1 expr2:等价于 and 操作符
  • expr1 -a expr2:等价于 and 操作符
  • expr1 -and expr2:expr1为true时候,以 expr1 搜索的结果为基础,进行 expr2,再返回 true 的结果;expr1 为 false 的时候,则直接忽略 expr2 不进行任何操作
  • expr1 -o expr2:等同于 or 操作符
  • expr1 -or expr2:只有 expr1 为 false 时候才评估 expr2
  • expr1,expr2:逗号操作符表示列表的意思,两者都会进行判断操作,但是 expr1 的判断结果是会被无视的,只有 expr2 的结果才是最终结果
## 取反
[root@iZrgngz5lz7qzsZ test]# ls
10.log  1.log  2.log  3.log  4.log  5.log  6.log  7.log  8.log  9.log
10.sh   1.sh   2.sh   3.sh   4.sh   5.sh   6.sh   7.sh   8.sh   9.sh
[root@iZrgngz5lz7qzsZ test]# find $(pwd) -not -name "*.log"
/home/test
/home/test/5.sh
/home/test/8.sh
/home/test/1.sh
/home/test/9.sh
/home/test/.bash_history
/home/test/3.sh
/home/test/.bash_profile
/home/test/.bash_logout
/home/test/10.sh
/home/test/4.sh
/home/test/.bashrc
/home/test/2.sh
/home/test/6.sh
/home/test/7.sh
[root@iZrgngz5lz7qzsZ test]#

## 以 expr2 结果为准
[root@iZrgngz5lz7qzsZ test]# find $(pwd) -name "*.log" , -name "*.sh"
/home/test/5.sh
/home/test/8.sh
/home/test/1.sh
/home/test/9.sh
/home/test/3.sh
/home/test/10.sh
/home/test/4.sh
/home/test/2.sh
/home/test/6.sh
/home/test/7.sh
[root@iZrgngz5lz7qzsZ test]#

## -and
[root@iZrgngz5lz7qzsZ test]# find $(pwd) -type f -and -name "*.log"
/home/test/10.log
/home/test/3.log
/home/test/1.log
/home/test/7.log
/home/test/6.log
/home/test/4.log
/home/test/8.log
/home/test/9.log
/home/test/2.log
/home/test/5.log
[root@iZrgngz5lz7qzsZ test]#

## -or
[root@iZrgngz5lz7qzsZ test]# find $(pwd) -type f -or -name "*.log"
/home/test/5.sh
/home/test/8.sh
/home/test/10.log
/home/test/3.log
/home/test/1.log
/home/test/1.sh
/home/test/7.log
/home/test/9.sh
/home/test/.bash_history
/home/test/3.sh
/home/test/6.log
/home/test/.bash_profile
/home/test/.bash_logout
/home/test/10.sh
/home/test/4.log
/home/test/8.log
/home/test/9.log
/home/test/4.sh
/home/test/2.log
/home/test/.bashrc
/home/test/2.sh
/home/test/6.sh
/home/test/5.log
/home/test/7.sh
[root@iZrgngz5lz7qzsZ test]#

expression-options

options 总是返回 true ,(除 -daystart)会影响所有指定的 test 表达式,options 会在命令行被解析后立即处理的,而 test 是在检索文件时候才处理的,大多数情况下,任何 options 部分都要写在 expression 最前面,不然会有警告信息出现

  • -daystart:指定以每天的开始(凌晨零点)计算关于天的时间,用于改变时间类的计算方式
  • -depth:搜索目录时候,先处理目录中文件或子目录,再处理目录本身
  • -maxdepth levels:指定搜索的最大目录深度,只能是非负整数
[root@iZrgngz5lz7qzsZ home]# ls
1.sh  admin  test
[root@iZrgngz5lz7qzsZ home]# find /home -maxdepth 1 -name "*.sh"
/home/1.sh
[root@iZrgngz5lz7qzsZ home]# find /home -maxdepth 2 -name "*.sh"
/home/1.sh
/home/test/5.sh
/home/test/8.sh
/home/test/1.sh
/home/test/9.sh
/home/test/3.sh
/home/test/10.sh
/home/test/4.sh
/home/test/2.sh
/home/test/6.sh
/home/test/7.sh
[root@iZrgngz5lz7qzsZ home]#
  • -mindepth levels:指定搜索的最小目录深度,1表示所有的文件

  • -ignore_readdir_race:当无法用 stat 检查文件信息时候没有权限,会给出错误信息,选项可忽略该信息

  • -warn:忽略警告信息

expression-tests

在搜索文件中,每次检查的文件都会被 test 表达式进行测试,true 的将会保留

  • 数值部分:+n 大于n;-n 小于n;=n 等于n

    • 对于文件大小而言:就是大于小于或等于多少KB

    • 对于时间而言:-n:n 天以内 +n:n 天以前 =n:前第 n 天 (这地方有点迷糊)

  • -type:文件类型

    • b:块设备文件
    • c:字符设备文件
    • d:目录
    • p:命名管道文件
    • f:普通文件
    • l:符号链接文件(软链接)
    • s:套接字文件
  • -size:文件大小,单位(b、c、w、k、M、G)

    [root@iZrgngz5lz7qzsZ ~]# find / -ignore_readdir_race -size +100M  -type f
    /usr/lib/locale/locale-archive
    /proc/kcore
    
  • -name:文件的 basename 可以被通配符匹配到,但是不能匹配“a/b”之类的,这种的需要使用“-path”模式,通配符字符* ? [] 是能够匹配到隐藏文件的。实践中,通常会用引号包围需要匹配的

[root@iZrgngz5lz7qzsZ ~]# find /home -name "*.log"
/home/test/10.log
/home/test/3.log
/home/test/1.log
/home/test/7.log
/home/test/6.log
/home/test/4.log
/home/test/8.log
/home/test/9.log
/home/test/2.log
/home/test/5.log
[root@iZrgngz5lz7qzsZ ~]#
  • -iname:不区分大小写匹配

  • -path:文件名能被通配符匹配到的,通配符字符* ? [] 不认为字符“/”“.”是特殊字符,这2个字符也在匹配范围内

  • -ipath:不区分大小写匹配

  • -regex:文件名被正则表达式匹配到,默认使用的正则是 Emacs类的,

  • -regextype:改变正则类型匹配

  • -iregex:不区分大小写

  • -perm:权限类

    • -perm mode:精确匹配给定的权限条件,比如:-perm g=w
    • -perm -mode:匹配完全包含给定权限的文件,至少的匹配关系
    • -perm /mode:匹配任意给定的权限的文件
  • -executable:具有可执行权限的文件,会考虑 ACL 等的特殊权限

  • -readable:具有可读权限的文件,它会考虑 ACL 等的特殊权限

  • -writable:具有可写权限的文件,它会考虑 ACL 等的特殊权限

  • 所属组/所属主的权限:

    • -gid:相关 gid 的文件
    • -group:相关组名的文件
    • -uid:文件所有者的 uid 的文件
    • -user:文件所有者的名字的文件
    • -nogroup:匹配所属组为数字格式的 gid,但是 gid 没有对应组名
    • -nouser:匹配所有者为数字格式的 uid,但是 uid 没有对应的用户名
  • 时间戳权限:

    • -anewer file:atime比mtime更接近现在的文件,即:文件修改过之后被访问过
    • -cnewer file:ctime比mtime更接近现在的文件
    • -newer file:比给定文件的mtime更接近现在的文件。
    • -newer[acm]t TIME:atime/ctime/mtime比时间戳TIME更新的文件
    • -amin n:文件的atime在范围n分钟内改变过。注意:n可以是(±)n,如-amin +3表示在3分钟以前
    • -cmin n:文件的ctime在范围n分钟内改变过
    • -mmin n:文件的mtime在范围n分钟内改变过
    • -atime n:文件的atime在范围24*n小时内改变过
    • -ctime n:文件的ctime在范围24*n小时内改变过
    • -mtime n:文件的mtime在范围24*n小时内改变过
    • -used n:最近一次ctime改变n天范围内,atime改变过的文件,即:atime比ctime晚n天的文件,可以是(±)n
  • 软硬链接类测试条件:

    • -samefile name:找出指定文件同indoe的文件,即其硬链接文件
    • -inum n:inode号为n的文件,可用来找出硬链接文件,但使用"-samefile"比此方式更方便
    • -links n:有n个软链接的文件
  • 杂项:

    • -false:总是返回 false
    • -true:总是返回 true

expression-actions

  • -delete:删除文件,删除成功返回 true,删除失败返回错误信息

  • -exec command ; :执行特定的命令,命令返回状态为0,则返回 true,command 后面所有的内容都被当做命令的参数,知道分号“;”为止,其中参数部分使用字符串“{}”时,表示 find 找到的结果,即在执行后续的命令时候,“{}”会被注逐一替换成 find 匹配到的结果,它可以出现在参数中的任何位置,只要出现,就会被结果替换,“;”分号需要转义,“{}”最好也用引号包围起来

  • -ok command ;:类似于上述情况,在执行前会交互式进行询问,如果不同意,不执行命令并返回 false,如果同意,则执行命令,但执行的命令是从 /dev/null 读取输入的(没懂)

  • -print:总是返回 true,默认的 action,

  • -printf:格式化输出

  • -print0:不换行输出

  • -prune:不进入目录,可用于忽略目录,但是不会忽略普通文件

  • -ls:总是返回 true,找到的文件以“ls -dils”格式输出

[root@iZrgngz5lz7qzsZ /]# ll /home/test/
total 0
-rw-r--r-- 1 root root 0 Sep  5 11:40 1.log
-rw-r--r-- 1 root root 0 Sep  5 11:40 2.log
-rw-r--r-- 1 root root 0 Sep  5 11:40 3.log
-rw-r--r-- 1 root root 0 Sep  5 11:40 4.log
[root@iZrgngz5lz7qzsZ /]# find /home/test/ -name "1.log" -exec ls -l '{}' \;
-rw-r--r-- 1 root root 0 Sep  5 11:40 /home/test/1.log
[root@iZrgngz5lz7qzsZ /]# find /home/test/ -name "1.log" -ok ls -l '{}' \;
< ls ... /home/test/1.log > ? y
-rw-r--r-- 1 root root 0 Sep  5 11:40 /home/test/1.log
[root@iZrgngz5lz7qzsZ /]#


[root@iZrgngz5lz7qzsZ /]# find /home/test/ -name "2.log" -ls
1055103    0 -rw-r--r--   1 root     root            0 Sep  5 11:40 /home/test/2.log
[root@iZrgngz5lz7qzsZ /]#


[root@iZrgngz5lz7qzsZ /]# find /home/test/ -name "2.log" -delete
[root@iZrgngz5lz7qzsZ /]# ll /home/test/
total 0
-rw-r--r-- 1 root root 0 Sep  5 11:40 3.log
-rw-r--r-- 1 root root 0 Sep  5 11:40 4.log
[root@iZrgngz5lz7qzsZ /]#

find 中的逻辑理解方式:debug

-D debug

使用调试模式可以知道 find 是按照什么逻辑处理各个选项的

find -D help

[root@iZrgngz5lz7qzsZ /]# find -D help
Valid arguments for -D:
help       Explain the various -D options
tree       Display the expression tree
search     Navigate the directory tree verbosely
stat       Trace calls to stat(2) and lstat(2)
rates      Indicate how often each predicate succeeded
opt        Show diagnostic information relating to optimisation
exec       Show diagnostic information relating to -exec, -execdir, -ok and -okdir
[root@iZrgngz5lz7qzsZ /]#

[root@iZrgngz5lz7qzsZ test]# find -D rates $(pwd) -name "*.sh" -o -name "*.log"
/home/test/3.log
/home/test/4.log
Predicate success rates after completion:
 ( -name *.log [0.8] [2/7=0.285714] -o [1] [2/7=0.285714] -name *.sh [0.8] [0/5=0]  ) -a [1] [2/7=0.285714] -print [1] [2/2=1]
[root@iZrgngz5lz7qzsZ test]#

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值