如何使用查找和定位在Linux上搜索文件

来自菜鸟教程
跳转至:导航、​搜索

介绍

用户在第一次学习如何使用 Linux 时遇到的一个问题是如何找到他们正在寻找的文件。

本指南将介绍如何使用恰当命名的 find 命令。 这将帮助您使用各种过滤器和参数搜索系统上的文件。 它还将简要介绍 locate 命令,该命令可用于以不同方式搜索文件。

先决条件

要遵循本指南,您需要访问运行基于 Linux 的操作系统的计算机。 这可以是您使用 SSH 连接到的虚拟专用服务器,也可以是您的本地计算机。 请注意,本教程使用运行 Ubuntu 20.04 的 Linux 服务器进行了验证,但给出的示例应该适用于运行任何版本的任何 Linux 发行版的计算机。

如果您打算使用远程服务器来遵循本指南,我们建议您先完成我们的 初始服务器设置指南 。 这样做将为您设置一个安全的服务器环境——包括一个具有 sudo 权限的非 root 用户和一个配置了 UFW 的防火墙——您可以使用它来培养您的 Linux 技能。

或者,您可以使用此页面上嵌入的交互式终端来试验本教程中的示例命令。 单击以下 Launch an Interactive Terminal! 按钮以打开终端窗口并开始使用 Linux (Ubuntu) 环境。

启动交互式终端!

注意:为了说明 findlocate 命令的工作原理,本指南中的示例命令搜索存储在 /下的文件]根目录。 因此,如果您以非 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。 您还可以返回满足 either 表达式的结果,方法是使用 -or 选项分隔它们:

find -name query_1 -or -name query_2

此示例将查找名称与 query_1query_2 匹配的任何文件。


按时间和大小过滤

find 为您提供了多种按大小和时间过滤结果的方法。

尺寸

您可以使用 -size 参数按文件大小过滤文件。 为此,您必须在数值大小值的末尾添加一个特殊后缀,以指示您是以字节、兆字节、千兆字节还是其他大小来计算大小。 以下是一些常用的尺寸后缀:

  • c:字节
  • k:千字节
  • M:兆字节
  • G:千兆字节
  • b:512 字节块

为了说明,以下命令将在 /usr 目录中查找每个正好 50 个字节的文件:

find /usr -size 50c

要查找小于 50 字节的文件,您可以改用以下语法:

find /usr -size -50c

要在 /usr 目录中查找超过 700 兆字节的文件,可以使用以下命令:

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

同样,您可以通过键入以下内容指定 shadow 组拥有的 /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 行。

find 结果上执行命令

您可以使用以下语法使用 -exec 参数对 find 匹配的所有内容执行任意辅助命令:

find find_parameters -exec command_and_options {} \;

{} 用作 find 匹配的文件的占位符。 \;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 命令。 此命令通常更快,并且可以轻松搜索整个文件系统。

您可以使用 apt 在 Debian 或 Ubuntu 上安装命令,方法是更新您的软件包列表,然后安装 mlocate 软件包:

sudo apt update
sudo apt install mlocate

在 Rocky Linux、CentOS 和其他 RedHat 派生发行版上,您可以改为使用 dnf 命令安装 mlocate

sudo dnf install mlocate

locatefind 快的原因是它依赖于列出文件系统上所有文件的数据库。 此数据库通常每天使用 cron 脚本更新一次,但您可以使用 updatedb 命令手动更新它。 现在使用 sudo 权限运行此命令:

sudo updatedb

请记住,如果要查找新文件,locate 数据库必须始终是最新的。 如果在执行 cron 脚本之前或在运行 updatedb 命令之前添加新文件,它们将不会出现在查询结果中。

locate 允许您以多种方式过滤结果。 使用它查找文件的最基本方法是使用以下语法:

locate query

这将匹配文件路径中任何位置包含字符串 query 的任何文件和目录。 要仅返回名称包含查询本身的文件,而不是在通向它的目录中包含查询的每个文件,您可以包含 -b 标志以仅搜索“基本名称”与查询匹配的文件:

locate -b query

要让 locate 只返回文件系统中仍然存在的结果(意味着在最后一次 updatedb 调用和当前 locate 调用之间未删除的文件),请使用 [X183X ] 标志:

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

这对于深入了解系统上存在多少文件和目录很有用。

结论

findlocate 命令都是在系统上查找文件的有用工具。 两者都是强大的命令,可以通过管道将它们与其他实用程序相结合来加强,但由您决定哪种工具适合您的特定情况。

从这里开始,我们鼓励您继续尝试 findlocate。 您可以阅读他们各自的 man 页面以了解本指南未涵盖的其他选项,并且您可以通过将搜索结果传递到 wc、[X207X 等其他命令来分析和操作搜索结果] 和 grep