文件查找locate和find

本文最后更新于:2023年12月5日 晚上

locate

find 去硬盘搜索,locate 是去数据库搜索,系统预建的文件索引数据库:/var/lib/mlocate/mlocate.db
执行updatedb更新数据库,这个命令构建索引的过程需要遍历整个根文件系统,很消耗 io 资源,所以在服务器比较繁忙的时候不要执行

locate [OPTION]... [PATTERN]...

-i      # 不区分大小写的搜索
-n N    # 只列举前N个匹配项目
-r      # 使用基本正则表达式

支持模糊搜索:

lujinkai@Z510:~/data/test$ locate `pwd`/*sh
/home/lujinkai/data/test/a.sh
/home/lujinkai/data/test/b.sh
/home/lujinkai/data/test/c_r.sh
/home/lujinkai/data/test/test.sh
/home/lujinkai/data/test/test2.sh

find

locate 查询的不是实时数据,find 查询的是实时的,因为 find 是去遍历指定路径完成文件查找

find [OPTION]... [path...] [expression]

OPTION

-P   # 找到符号链接的时候,所有的属性都来自符号链接,从来不follow symbolic links。这是默认选项
-L   # 找到符号链接的时候,所有的属性来自文件本身,总是follow symbolic links。而不是符号链接
-H   # 仅仅当作为命令行参数时,也就是这里的[path...],才会follow symbolic links

expression

描述了如何匹配文件以及如何处理匹配的文件。一个 expression 是由以下多个选项组成:

- Tests
- Actions
- Global options
- Positional options
- Operators

如果整个 expression 没有包含任何选项,默认 -print

-delete 也类似一个选项,因为它隐含 -depth 选项

Positional options 位置选项

位置选项总是返回 true。位置选项会影响所有指定的 Tests,哪怕 Tests 写在前面(除了-daystart,-daystart 只影响写在其后面的 Tests),为了易读性,最好把位置选项放在 expression 的开头部分

  • -daystart
    指定每天的开始是 0 点而不是 24 小时之前,例如:当前时间是 8 月 13 日 8 点,要求搜索 2 天内修改过的文件,默认搜索文件的起点是 8 月 11 日 8 点,如果使用-daystart 选项,则搜索文件的起点是 8 月 11 日 0 点

    影响的 Tests:-amin,-atime,-cmin,-ctime,-mmin、-mtime

  • -follow
    这个选项已经被弃用,使用-L 代替

  • -regextype type
    不常用,先略过。。。

    影响的 Tests:-regex、-iregex

  • -warn,-nowarn
    打开或关闭警告信息,具体看 man 帮助

Global options 全局选项

Global options 也总是返回 true,对所有的

  • -d
    已弃用,等同于-depth 的,与 FreeBSD、NetBSD、MacOSX 和 OpenBSD 兼容.

  • -depth
    搜索到目录时,先处理目录中的文件,再处理目录本身。对于-delete 这个 action,它隐含-depth 选项

  • -ignore_readdir_race
    在 find 统计文件的时候,如果有其他操作把这文件删了,会报错,加上这个选项就不报错了

  • -noignore_readdir_race
    关闭-ignore_readdir_race.

  • -maxdepth levels
    最大搜索目录深度,指定目录下的文件为第 1 级

  • -mindepth levels
    最小搜索目录深度

  • -mount
    不搜索其他文件系统,-xdev 的替代名称,用于与 find 的其他版本兼容

  • -xdev
    不搜索其他文件系统

  • -noleaf
    禁止在非 UNUX 文件系统,MS-DOS 系统,CD-ROM 文件系统中进行最优化查找,具体什么意思没太看懂

  • -help,–help
    打印帮助信息,并且退出

  • -version
    打印 find 版本号然后退出

Tests 测试

关于选项的参数是数字的,n 表示等于 n,+n 表示大于 n,-n 表示小于 n,例如:-uid 0表示要求 uid 等于 0,-uid +0要求 uid 大于 0

时间戳

n:n 个时间单位之内
+n:n 个时间单位之前
atime:access time,访问时间,文件中的数据库最后被访问的时间
mtime:modify time,修改时间,文件内容被修改的最后时间
ctime:change time,变化时间,文件的原数据,发生改变的时间

  • -amin n
    a:atime、min:minutes
    n:搜索 atime 在 n 分钟内有改变的文件
    +n:搜索 atime 在 n 分钟之前有改变的文件

  • -mmin n
    m:mtime

  • -cmin n
    c:ctime

  • -atime n、-ctime n、-mtime n
    和 amin、mmin、cmin 的区别在于时间单位为天,也就是 24 小时,从现在往前数 24×n 小时

  • -used n
    查找 atime 在 ctime 后 n 天的文件

  • -anewer file
    搜索 atime 比给定 file 的 mtime 还要晚的文件。换言之,在 file 的内容被修改后,又访问了哪些文件?

  • -cnewer file
    搜索 ctime 比给定 file 的 mtime 还要晚的文件。

  • -new file
    搜索 mtime 比给定文件的 mtime 还要晚的文件。

-newerXY reference
X 和 Y 是占位符,主要是查找 X 时间戳比 reference 的 Y 时间戳更新的文件。
reference 可以是时间字符串(参考 date -d 格式,推荐使用 yyyy-MM-dd hh:mm:ss),也可以是
X 可以是 a、B、c、m,Y 可以是 a、B、c、m、t。
a:atime;
B:birth time 文件的出生日期,不是所有系统都支持这个参数;
c:ctime;
t:代表 reference 本身,此时 reference 必须是时间,不能是文件,显然只有 Y 可以设为 t,X 设为 t 是没有意义的

范例:获取 mtime 为昨天的文件

lujinkai@Z510:~/data/test$ find . -newermt $(date -d '-1 day' +%F) ! -newermt $(date +%F)
./issue
./re.txt
lujinkai@Z510:~/data/test$ find . -newermt '2020-08-12 00:00:00' ! -newermt '2020-08-13 00:00:00'
./issue
./re.txt
文件名和 inode
  • -name pattern
    文件的 basename 与 pattern 匹配,支持使用通配符,注意,这里的 pattern 的 *、?、[] 是可以匹配.开头的文件,也就是隐藏文件(在 bash 中,是无法匹配的)

  • -iname pattern
    不区分大小写的 name

  • -lname pattern
    找找符合指定匹配模式的符号链接文件,该选项与-L 冲突

  • -ilname pattern
    不区分大小写的 lname

  • -inum n
    按照 inode 号查找

  • -samefile name
    找出指定文件同 inode 号的文件,即其硬链接

  • -links n
    File has n hard links.

  • -regex pattern
    -name 只能匹配 basename,-regex 可以匹配整个文件路径,匹配规则是正则表达式

  • -iregex pattern
    相比 regex,iregex 对匹配的内容不区分大小写

  • -path pattern
    和-regex pattern 相比,-path pattern 的匹配规则是通配符

  • -ipath pattern
    不区分大小写的 path

  • -wholename pattern
    不推荐使用,可以使用 -path 代替

  • -iwholename pattern
    不区分大小写的 wholename

属主、属组
  • -user uname
    uname 可以是用户名,也可以是 uid
  • -group gname
    gname 可以是组名,也可以是 gid
  • -uid n
    文件的属主 id 是 n
  • -gid n
    文件的属组 id 是 n
  • -nouser
    查找没有属主的文件
  • -nogroup
    查找没有属组的文件
文件类型
  • -type c
    c 可以是以下类型:
    b(block)、c(character)、d(directory)、p(FIFO)、f(regular file)、l(symbolic link)、s(socket)、D(门 (Solaris 特有))
    当搜索多个文件类型时,可以用逗号分割
空文件或目录
  • -empty
    查找空文件和空目录
文件大小
  • -size n[cwbkMG]
    c:1 字节、w:2 字节、b:512 字节(默认)、k:1k、M:1M、G:1G
    n 的前缀+和-表示大于和小于,对比目标文件时,对文件的 size 进行四舍五入,精度就是指定的 cwbkMG,例如:-size -1M并不等同于-size -1048576c。前者只匹配空文件,后者匹配 0 到 1048575 字节的文件。
权限
  • -perm mode
    精确匹配文件权限,必须提供全部的权限,不提供的默认此权限为 0,mode 推荐使用八进制模式,如果使用符号模式,可能会比较复杂,例如:-perm g=w只能匹配到模式为 0020 的文件

  • -perm /mode
    可以提供 1 个或多个权限,只要满足其中一个权限,就能匹配,例如:-perm /u=rwx,u 满足 rwx 中一项即可;-perm /222,ugo 中只要有一个具有写权限即可

  • -perm -mode
    可以提供 1 个或多个权限,无论提供多少权限,必须全部满足,才能匹配,例如:-perm /u=rwx,u 必须全部满足 rwx;-perm /222,ugo 都要具有写权限

  • -perm +mode
    已淘汰,使用 -perm /mode 代替

  • -writable
    匹配当前用户可写的文件

  • -readable
    匹配当前用户可读的文件。-perm 测试文件的 ugo 的权限,而-writable 和-readable 测试当前用户对文件的权限

其他
  • -executable
    查找可以被执行的文件(sh、bin 文件),和可以被搜索的目录

  • -true
    总是返回 true

  • -false
    总是返回 false

  • -fstype type
    指定文件系统的类型,本机的文件系统类型在/etc/fstab 中可以查看

  • -xtype c
    和“-type”相同,除非文件是符号链接。对于符号链接,-xtype 检查-type 不检查的文件的类型。
    具体什么意思,还不太清楚

  • -context pattern
    只限 SELinux,因为 SELinux 我们都会关掉,所以这个选项没什么用

ACTIONS 动作

  • -print
    默认的处理动作,输出内容到终端

  • -delete
    删除文件,删除成功返回 true,删除失败报错

  • -ls
    对处理后的内容执行类似ls -l的操作

  • -ok command {} ;
    对查找到的每个文件执行 command,对于每个文件执行命令之前,都会交互式要求用户确认,{}用于引用查找到的文件名称自身

  • -exec command {} ;
    对查找到的每个文件执行由 COMMAND 指定的命令,{}用于引用查找到的文件名称自身

  • -fls file
    查找到的所有文件的长格式信息保存至指定文件中

  • -prune
    如果该文件是一个目录,则不要下降到它,该选项和-depth 冲突,如果设置了-depth 选项,该选项失效

  • -quit

OPERATORS 操作

  • ( expr )
    强制优先

  • !expr
    取反

  • expr1 expr2
    隐含的“与“操作

  • expr1 -a expr2
    和“expr1 expr2“一样

  • expr1 -o expr2
    “或“操作

  • expr1 , expr2

替换参数 xargs

xargs 读取标准输入的内容,使用空格或回车(-n)将数据分割,可以直接输出,也可以作为参数传递给后面的命令

find 常常搭配 xargs 一起使用

find | xargs command

范例:

#显示10个数字
seq 10 | xargs
#删除当前目录下的大量文件
ls | xargs rm
#
find -name "*.sh" | xargs ls -Sl
[root@centos8 data]#echo {1..10} |xargs
1 2 3 4 5 6 7 8 9 10
[root@centos8 data]#echo {1..10} |xargs -n1
1
2
3
4
5
6
7
8
9
10
[root@centos8 data]#echo {1..10} |xargs -n2
1 2
3 4
5 6
7 8
9 10
#批量创建和删除用户
echo user{1..10} |xargs -n1 useradd
echo user{1..100} | xargs -n1 userdel -r
#这个命令是错误的
find /sbin/ -perm /700 | ls -l
#查找有特殊权限的文件,并排序
find /bin/ -perm /7000 | xargs ls -Sl
#此命令和上面有何区别?
find /bin/ -perm -7000 | xargs ls -Sl
#以字符nul分隔*
find -type f -name “*.txt” -print0 | xargs -0 rm
#并发执行多个进程
seq 100 |xargs -i -P10 wget -P /data
http://10.0.0.8/{}.html
#并行下载视频
seq 389 | xargs -i -P3 you-get https://www.bilibili.com/video/av36489007?p={}

练习

  1. 查找/var 目录下属主为 root,且属组为 mail 的所有文件
  2. 查找/var 目录下不属于 root、lp、gdm 的所有文件
  3. 查找/var 目录下最近一周内其内容修改过,同时属主不为 root,也不是 postfix 的文件
  4. 查找当前系统上没有属主或属组,且最近一个周内曾被访问过的文件
  5. 查找/etc 目录下大于 1M 且类型为普通文件的所有文件
  6. 查找/etc 目录下所有用户都没有写权限的文件
  7. 查找/etc 目录下至少有一类用户没有执行权限的文件
  8. 查找/etc/init.d 目录下,所有用户都有执行权限,且其它用户有写权限的文件

文件查找locate和find
http://blog.lujinkai.cn/运维/基础/tar和find/文件查找locate和find/
作者
像方便面一样的男子
发布于
2020年12月9日
更新于
2023年12月5日
许可协议