如何在 Linux 上使用查找和定位来搜索文件
介绍
用户在第一次学习如何使用 Linux 时遇到的一个问题是如何找到他们正在寻找的文件。
本指南将介绍如何使用恰当命名的 find
命令。这将帮助您使用各种过滤器和参数搜索系统上的文件。它还将简要介绍 locate
命令,该命令可用于以不同的方式搜索文件。
先决条件
要按照本指南进行操作,您需要访问运行基于 Linux 的操作系统的计算机。这可以是您使用 SSH 连接到的虚拟专用服务器,也可以是您的本地计算机。请注意,本教程是使用运行 Ubuntu 20.04 的 Linux 服务器进行验证的,但给出的示例应该适用于运行任何版本的任何 Linux 发行版的计算机。
如果您计划使用远程服务器来遵循本指南,我们鼓励您首先完成我们的初始服务器设置指南。这样做将为您设置一个安全的服务器环境 — 包括具有 sudo
权限的非根用户和配置有 UFW 的防火墙 — 您可以使用它来培养您的 Linux 技能。
注意:为了说明 find
和 locate
命令的工作原理,本指南中的示例命令搜索存储在 /
或 根目录。因此,如果您以非 root 用户身份登录终端,一些示例命令的输出中可能包含 Permission denied
。
这是意料之中的,因为您正在搜索普通用户通常无权访问的目录中的文件。但是,这些示例命令应该仍然有效,并且有助于理解这些程序的工作原理。
按名称查找
搜索文件最明显的方法是按文件名。
要使用 find
命令按名称查找文件,您可以使用以下语法:
- find -name "query"
这将区分大小写,这意味着搜索 query
与搜索 Query
不同。
要按名称查找文件但忽略查询的大小写,请使用 -iname
选项:
- find -iname "query"
如果你想找到所有不符合特定模式的文件,你可以使用 -not
反转搜索:
- find -not -name "query_to_avoid"
或者,您可以使用感叹号 (!
) 反转搜索,如下所示:
- find \! -name "query_to_avoid"
请注意,如果您使用 !
,则必须使用反斜杠 (\
) 对字符进行转义,这样 shell 就不会在 find
之前尝试对其进行解释> 可以行动。
按类型查找
您可以使用 -type
参数指定要查找的文件类型。它是这样工作的:
- find -type type_descriptor query
以下是一些可用于指定文件类型的描述符:
f
: 普通文件d
: 目录l
:符号链接c
:字符设备b
:块设备
例如,如果你想找到你系统上的所有字符设备,你可以发出这个命令:
- find /dev -type c
此命令专门只搜索 /dev
目录中的设备,该目录通常在 Linux 系统中挂载设备文件:
Output/dev/vcsa5
/dev/vcsu5
/dev/vcs5
/dev/vcsa4
/dev/vcsu4
/dev/vcs4
/dev/vcsa3
/dev/vcsu3
/dev/vcs3
/dev/vcsa2
/dev/vcsu2
/dev/vcs2
. . .
您可以使用如下命令搜索所有以 .conf
结尾的文件。此示例在 /usr
目录中搜索匹配文件:
- find /usr -type f -name "*.conf"
Output/usr/src/linux-headers-5.4.0-88-generic/include/config/auto.conf
/usr/src/linux-headers-5.4.0-88-generic/include/config/tristate.conf
/usr/src/linux-headers-5.4.0-90-generic/include/config/auto.conf
/usr/src/linux-headers-5.4.0-90-generic/include/config/tristate.conf
/usr/share/adduser/adduser.conf
/usr/share/ufw/ufw.conf
/usr/share/popularity-contest/default.conf
/usr/share/byobu/keybindings/tmux-screen-keys.conf
/usr/share/libc-bin/nsswitch.conf
/usr/share/rsyslog/50-default.conf
. . .
注意:前面的例子结合了两个find
查询表达式;即,-type f
和 -name *.conf
。对于要返回的任何文件,它必须同时满足这两个表达式。
您可以通过使用 -and
选项将它们分开来组合这样的表达式,但如本例所示,只要您包含两个表达式,就隐含了 -and
。您还可以通过使用 -or
选项分隔它们来返回满足任一表达式的结果:
- find -name query_1 -or -name query_2
此示例将查找名称匹配 query_1
或 query_2
的所有文件。
按时间和大小过滤
find
为您提供了多种按大小和时间过滤结果的方法。
尺寸
您可以使用 -size
参数按大小过滤文件。为此,您必须在数字大小值的末尾添加一个特殊的后缀,以指示您是按字节、兆字节、千兆字节还是其他大小来计算大小。以下是一些常用的尺寸后缀:
c
:字节数k
:千字节M
:兆字节G
:千兆字节b
:512 字节块
为了说明,以下命令将在 /usr
目录中找到恰好 50 字节的每个文件:
- find /usr -size 50c
要查找小于 50 字节的文件,您可以改用以下语法:
- find /usr -size -50c
要在 /usr
目录中查找超过 700 MB 的文件,您可以使用以下命令:
- find /usr -size +700M
时间
对于系统上的每个文件,Linux 都会存储有关访问时间、修改时间和更改时间的时间数据。
- <李> 访问时间:上次读取或写入文件的时间。 <李> 修改时间:上次修改文件内容的时间。 <李> 更改时间:上次更改文件的 inode 元数据的时间。
您可以使用 -atime
、-mtime
和 -ctime
选项根据这些参数进行find
搜索,分别。对于这些选项中的任何一个,您都必须传递一个值来指示您要搜索过去多少天。与前面概述的大小选项类似,您可以在这些选项前面加上加号或减号来指定“大于”或“小于”。
例如,要在 /usr
目录中查找最近一天内修改过的文件,请运行以下命令:
- find /usr -mtime 1
如果你想要不到一天前访问过的文件,你可以运行这个命令:
- find /usr -atime -1
要查找元信息最后更改时间超过 3 天的文件,您可以执行以下命令:
- find /usr -ctime +3
这些选项还有配套参数,您可以使用它们来指定分钟而不是天:
- find /usr -mmin -1
这将给出最后一分钟修改的文件。
find
还可以与参考文件进行比较并返回较新的文件:
- find / -newer reference_file
此语法将返回系统上比参考文件最近创建或更改的每个文件。
按所有者和权限查找
您还可以分别使用 -user
和 -group
参数按拥有文件的用户或组搜索文件。要查找 syslog 用户拥有的 /var
目录中的每个文件,请运行以下命令:
- find /var -user syslog
类似地,您可以通过键入以下命令指定影子组拥有的 /etc
目录中的文件:
- find /etc -group shadow
您还可以搜索具有特定权限的文件。
如果要匹配一组精确的权限,可以使用此语法使用八进制表示法指定权限:
- find / -perm 644
这将匹配具有指定权限的文件。
如果你想指定至少具有这些权限的任何内容,你可以在权限符号之前加上减号:
- find / -perm -644
这将匹配任何具有附加权限的文件。在这种情况下,将匹配具有 744
权限的文件。
按深度过滤
在本节中,您将创建一个示例目录结构,然后您将使用该目录结构按文件在结构中的深度来探索过滤文件。
如果您按照本教程中的示例进行操作,那么在 /tmp/
目录中创建这些文件和目录是明智的。 /tmp/
是一个临时目录,这意味着下次服务器启动时,其中的任何文件和目录都将被删除。这对于本指南的目的很有用,因为您可以根据需要创建任意数量的目录、文件和链接,而不必担心它们以后会阻塞您的系统。
运行本节命令后,您的/tmp/
目录将包含三级目录,第一级有十个目录。每个目录(包括临时目录)将包含十个文件和十个子目录。
使用以下命令在 /tmp/
目录中创建示例目录结构:
- mkdir -p /tmp/test/level1dir{1..10}/level2dir{1..10}/level3dir{1..10}
然后,使用 touch
命令用一些示例文件填充这些目录:
- touch /tmp/test/{file{1..10},level1dir{1..10}/{file{1..10},level2dir{1..10}/{file{1..10},level3dir{1..10}/file{1..10}}}}
有了这些文件和目录,继续导航到您刚刚创建的 test/
目录:
- cd /tmp/test
要基本了解 find
将如何从此结构中检索文件,请从匹配任何名为 file1
的文件的常规名称搜索开始:
- find -name file1
Output./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
./level1dir7/level2dir8/level3dir6/file1
./level1dir7/level2dir8/level3dir5/file1
./level1dir7/level2dir8/file1
. . .
这将返回很多结果。如果将输出通过管道传输到计数器,您会发现总共有 1111
个结果:
- find -name file1 | wc -l
Output1111
在大多数情况下,这可能是对您有用的太多结果。要缩小范围,可以在顶级搜索目录下指定搜索的最大深度:
- find -maxdepth num -name query
要仅在 level1
目录及以上目录中查找 file1
,您可以将最大深度指定为 2(顶级目录为 1,level1 为 1
目录):
- find -maxdepth 2 -name file1
Output./level1dir7/file1
./level1dir1/file1
./level1dir3/file1
./level1dir8/file1
./level1dir6/file1
./file1
./level1dir2/file1
./level1dir9/file1
./level1dir4/file1
./level1dir5/file1
./level1dir10/file1
这是一个更易于管理的列表。
如果您知道所有文件都存在于当前目录下的特定点之后,您还可以指定最小目录:
- find -mindepth num -name query
您可以使用它来仅查找目录分支末尾的文件:
- find -mindepth 4 -name file1
Output./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
. . .
同样,由于分支目录结构,这将返回大量结果 (1000)。
您可以组合最小和最大深度参数以集中在一个狭窄的范围内:
- find -mindepth 2 -maxdepth 3 -name file1
Output./level1dir7/level2dir8/file1
./level1dir7/level2dir5/file1
./level1dir7/level2dir7/file1
./level1dir7/level2dir2/file1
./level1dir7/level2dir10/file1
./level1dir7/level2dir6/file1
./level1dir7/level2dir3/file1
./level1dir7/level2dir4/file1
./level1dir7/file1
. . .
像这样组合这些选项可以显着缩小结果范围,只返回 110 行而不是之前的 1000 行。
在查找结果上执行命令
您可以使用 -exec
参数对 find
匹配的所有内容执行任意帮助程序命令,语法如下:
- find find_parameters -exec command_and_options {} \;
{}
用作查找
匹配的文件的占位符。 \;
让 find
知道命令在哪里结束。
例如,假设您仍在上一步中在 /tmp/
目录中创建的 test/
目录中,您可以找到上一节中的文件有 644
权限并将它们修改为具有 664
权限:
- find . -type f -perm 644 -exec chmod 664 {} \;
您还可以以类似的方式更改目录权限:
- find . -type d -perm 755 -exec chmod 700 {} \;
此示例查找权限设置为 755
的每个目录,然后将权限修改为 700
。
使用 locate 查找文件
find
的替代方法是 locate
命令。此命令通常更快并且可以轻松搜索整个文件系统。
您可以通过更新软件包列表然后安装 mlocate
软件包,使用 apt
在 Debian 或 Ubuntu 上安装命令:
- sudo apt update
- sudo apt install mlocate
在 Rocky Linux、CentOS 和其他 RedHat 派生发行版上,您可以改为使用 dnf
命令来安装 mlocate
:
- sudo dnf install mlocate
locate
比 find
快的原因是它依赖于一个列出文件系统上所有文件的数据库。该数据库通常使用 cron 脚本每天更新一次,但您可以使用 updatedb
命令手动更新它。现在使用 sudo
权限运行此命令:
- sudo updatedb
请记住,如果您想查找新文件,locate
数据库必须始终是最新的。如果您在执行 cron 脚本之前或在运行 updatedb
命令之前添加新文件,它们将不会出现在您的查询结果中。
locate
允许您以多种方式过滤结果。使用它查找文件的最基本方法是使用以下语法:
- locate query
这将匹配文件路径中任何位置包含字符串 query
的任何文件和目录。要仅返回其名称包含查询本身的文件,而不是在其前面的目录中包含查询的每个文件,您可以包含 -b
标志以仅搜索其 \basename ” 匹配查询:
- locate -b query
让 locate
只返回仍然存在于文件系统中的结果(意味着在上次 updatedb
调用和当前 locate
调用之间没有被删除的文件), 使用 -e
标志:
- locate -e query
您可以使用 -S
选项检索有关 locate
已编目的信息的统计信息:
- locate -S
OutputDatabase /var/lib/mlocate/mlocate.db:
21015 directories
136787 files
7727763 bytes in file names
3264413 bytes used to store database
这对于深入了解系统上存在多少文件和目录很有用。
结论
find
和 locate
命令都是在系统上查找文件的有用工具。两者都是功能强大的命令,可以通过管道将它们与其他实用程序结合起来得到加强,但由您决定哪种工具适合您的给定情况。
从这里开始,我们鼓励您继续尝试使用 find
和 locate
。您可以阅读它们各自的 man
页面以了解本指南中未涵盖的其他选项,您可以通过将搜索结果输送到其他命令(例如 wc
、sort
和 grep
。