在 Linux 中查找文件与命令

CompTIABeginner
立即练习

介绍

在本实验中,你将掌握在 Linux 命令行环境中定位文件和命令的核心技术。首先,你将使用功能强大的 find 命令,学习如何进行基础的按名搜索,并利用通配符实现更灵活的模式匹配。这种实战演练将引导你创建一个示例目录结构,以便安全地练习搜索技能。

在此基础上,你将探索如何使用 -execxargs 对搜索结果执行命令。本实验还将涵盖其他专门的搜索工具,包括基于数据库的快速搜索工具 locate,用于查找命令二进制文件和手册的 whereis,以及用于分析命令执行路径的 aliaswhichtype 等实用程序。完成本实验后,你将能够熟练地为任何文件或命令搜索任务选择合适的工具。

使用 find 和通配符进行基础文件搜索

在这一步中,你将学习如何使用 find 命令,它是 Linux 命令行中用于搜索文件和目录最强大的工具之一。我们将从基础的按名搜索开始,并引入通配符来查找符合特定模式的文件。

首先,让我们创建一个专门的目录和一些示例文件进行练习。这可以确保我们有一个受控的环境来观察 find 的工作原理,而不会影响文件系统的其他部分。

  1. 确保你处于正确的起始目录。本实验的所有工作都将在 ~/project 中进行。
cd ~/project
  1. 创建一个名为 find_lab 的新目录并进入该目录。
mkdir find_lab
cd find_lab
  1. 现在,让我们创建一组文件和一个子目录供搜索。我们将使用 touch 命令创建空文件,使用 mkdir 创建目录。
touch file1.txt file2.log report.txt File1.TXT
mkdir subdir
touch subdir/file3.txt subdir/another.log

你可以使用 ls -R 命令验证结构,该命令会递归列出当前目录及其子目录中的文件。

ls -R

你应该会看到类似如下的输出:

.:
File1.TXT  file1.txt  file2.log  report.txt  subdir

./subdir:
another.log  file3.txt

测试环境准备就绪后,让我们开始搜索。

find 命令的基本语法是 find [path] [expression][path] 告诉 find 从哪里开始搜索,而 [expression] 定义了要查找的内容。

按精确文件名搜索

要通过精确名称查找文件,可以使用 -name 表达式。让我们查找文件 report.txt。我们将使用 . 作为路径,这告诉 find 从当前目录开始搜索。

find . -name "report.txt"

输出将显示找到的文件路径:

./report.txt

使用通配符搜索

通配符允许你根据模式搜索文件。最常用的通配符是星号(*),它可以匹配任何字符序列。

最佳实践是将模式包含在双引号(")中,以防止 Shell 在 find 命令使用通配符之前对其进行解释。

让我们查找所有以 .txt 扩展名结尾的文件。

find . -name "*.txt"

find 将递归搜索当前目录(.)及其所有子目录:

./file1.txt
./report.txt
./subdir/file3.txt

请注意,File1.TXT 没有被找到,因为 -name 执行的是区分大小写的搜索。要执行不区分大小写的搜索,请使用 -iname(insensitive name)表达式。

find . -iname "*.txt"

现在,输出包含了所有以 .txt 结尾的文件,无论大小写如何:

./file1.txt
./report.txt
./File1.TXT
./subdir/file3.txt

按文件类型搜索

你还可以使用 -type 表达式指示 find 仅查找特定类型的文件系统对象,例如文件或目录。使用 -type f 表示普通文件,-type d 表示目录。

让我们仅查找当前位置内的目录。

find . -type d

输出列出了当前目录(.)和我们创建的 subdir

.
./subdir

你可以组合多个表达式来创建更具体的搜索。例如,查找所有以 .log 结尾的文件(不包括目录):

find . -type f -name "*.log"

此命令将查找所有既是文件且名称以 .log 结尾的项目。

./file2.log
./subdir/another.log

你现在已经学习了配合名称模式和类型过滤器使用 find 的基础知识。在接下来的步骤中,我们将探索此命令更高级的功能。

使用 find -execxargs 对搜索结果执行操作

在这一步中,你将不仅仅是列出文件。你将学习如何直接对 find 命令找到的文件执行命令。这是一种执行批量操作的强大技术,例如更改权限、删除文件或运行自定义脚本。我们将介绍两种主要方法:find-exec 选项和 xargs 命令。

我们将继续在上一阶段创建的 ~/project/find_lab 目录中工作。首先,确保你处于正确的目录中。

cd ~/project/find_lab

使用 find -exec

-exec 选项允许你对 find 定位的每个文件运行任意命令。其语法起初可能看起来有点奇怪:

find [path] [expression] -exec [command] {} \;

  • [command]:你想要运行的命令(例如 ls -lrmchmod)。
  • {}:这是一个特殊的占位符。find 会将 {} 替换为它当前找到的文件完整路径。
  • \;:这是 -exec 命令必需的终止符。反斜杠(\)是必要的,用于防止 Shell 将分号解释为特殊字符。

让我们尝试一下。我们将查找所有扩展名为 .txt 的文件,并对每个文件运行 ls -l 以查看其详细信息。

find . -name "*.txt" -exec ls -l {} \;

输出显示了运行三次 ls -l 的结果,对应找到的每个 .txt 文件:

-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./file1.txt
-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./report.txt
-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./subdir/file3.txt

为了安全起见,find 提供了 -ok 选项,它的工作方式与 -exec 完全相同,但在对每个文件执行命令之前会提示你确认。在执行删除文件(rm)等破坏性操作时,强烈建议使用此选项。

让我们尝试删除之前创建的 .log 文件,但这次为了安全起见使用 -ok

find . -name "*.log" -ok rm {} \;

对于找到的每个文件,find 都会询问你的确认。输入 y 并按回车键批准删除。

< rm ... ./file2.log > ? y
< rm ... ./subdir/another.log > ? y

确认后,你可以通过列出目录内容来验证文件是否已消失。

ls -R
.:
File1.TXT  file1.txt  report.txt  subdir

./subdir:
file3.txt

使用 xargs

-exec 的另一种替代方案是将 find 的输出通过管道传递给 xargs 命令。xargs 从标准输入(由 find 提供的文件路径)读取项目,并以这些项目作为参数执行指定的命令。

xargs 的主要优势是效率。虽然 -exec ... \; 为每个文件运行一次命令,但 xargs 会将文件路径分组,并以多个参数的形式一次性运行较少次数的命令。

首先,让我们重新创建刚才删除的日志文件,以便有操作对象。

touch file2.log subdir/another.log

现在,让我们使用 findxargs 来列出 .log 文件的详细信息。

find . -name "*.log" | xargs ls -l

输出与 -exec 示例类似,但命令结构不同:

-rw-r--r-- 1 labex labex 0 <date> <time> ./file2.log
-rw-r--r-- 1 labex labex 0 <date> <time> ./subdir/another.log

find -ok 类似,xargs 也有一个使用 -p 选项的“提示”模式。它会显示即将运行的命令并询问你的确认。

让我们再次使用它来删除 .log 文件。

find . -name "*.log" | xargs -p rm

xargs 会将文件组合成一个 rm 命令并询问你的确认。输入 y 并按回车键。

rm ./file2.log ./subdir/another.log ?...y

你现在已成功使用 -execxargs 对搜索结果执行操作,这是在 Linux 中自动化任务的一项基本技能。

使用 locateupdatedb 进行基于数据库的快速搜索

在这一步中,你将学习 find 的替代方案,称为 locatefind 是实时搜索文件系统,而 locate 则是搜索预先构建的文件路径数据库。这使得 locate 的速度显著加快,但有一个关键的权衡:它只能找到数据库上次更新时已经存在的文件。

我们将继续在 ~/project 目录中工作。首先,确保安装了必要的工具。

  1. locate 命令由 mlocate 软件包提供,默认情况下可能未安装。运行以下命令更新软件包列表并安装它。由于这是系统级安装,你将使用 sudo
sudo apt-get update && sudo apt-get install -y mlocate

你会看到软件包安装进度,这是正常现象。

  1. 现在,让我们进入之前步骤中的测试目录。
cd ~/project/find_lab
  1. 尝试使用 locate 查找 report.txt 文件。
locate report.txt

在许多系统中,locate 数据库会自动更新,因此你可能会立即看到该文件:

/home/labex/project/find_lab/report.txt

如果你看到了文件路径,这意味着数据库已经包含了你最近创建的文件信息。当系统在后台自动运行数据库更新时,就会发生这种情况。

  1. 如果你在第 3 步中没有看到任何输出,则需要手动更新数据库。使用 updatedb 命令重建数据库:
sudo updatedb

此命令不产生输出,但在后台运行。它可能需要片刻时间才能完成。

  1. 运行 updatedb(如果需要)后,再次尝试 locate 命令:
locate report.txt

现在它应该能找到并显示文件的路径:

/home/labex/project/find_lab/report.txt

了解本地数据库的局限性

让我们探索一下在数据库上次更新后创建新文件会发生什么。

  1. 首先,在我们的 find_lab 目录中创建一个新文件。
touch special_report.pdf
  1. 尝试定位这个新文件:
locate special_report.pdf

如果系统数据库最近刚更新过,你可能会看到该文件。如果没有,则不会有输出,因为数据库还不知道这个新创建的文件。

  1. 你可以强制更新系统数据库:
sudo updatedb
  1. 现在再次尝试定位该文件:
locate special_report.pdf

你现在应该能看到:

/home/labex/project/find_lab/special_report.pdf

了解数据库更新频率

关键点在于 locate 取决于其数据库的新鲜度。在生产系统中:

  • 系统通常会自动更新 locate 数据库(通常通过 cron 任务每天更新)。
  • 当你需要立即获得结果时,可以使用 sudo updatedb 手动更新。
  • locate 极其快速,因为它搜索的是预构建的索引而不是扫描文件系统。
  • 对于查找非常近期创建的文件,find 可能更可靠,因为它执行的是实时搜索。

你现在已经了解了 locate 如何通过使用预构建数据库提供极速搜索,并理解了使用 updatedb 保持该数据库最新的重要性。

使用 whereis 定位命令二进制文件和手册

在这一步中,你将学习使用 whereis,这是一个专门用于定位命令的二进制文件、源代码和手册页文件的命令。与用于通用文件搜索的 findlocate 不同,whereis 针对快速查找与系统命令相关的核心文件进行了优化。它通过搜索预定义的标准 Linux 目录列表来工作,因此速度极快。

让我们开始探索 whereis 命令。你可以在任何目录中执行此操作,因为 whereis 不会相对于你的当前位置进行搜索。为了保持一致性,我们将留在 ~/project 目录中。

cd ~/project
  1. 让我们查找 passwd 命令的位置,该命令用于更改用户密码。
whereis passwd

输出显示了命令名称,随后是其二进制可执行文件和相关手册页的路径。

passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
  • /usr/bin/passwd:这是可执行程序。
  • /etc/passwd:这是系统的用户数据库文件,passwd 命令会与其交互。whereis 经常在结果中包含重要的配置文件。
  • /usr/share/man/...:这些是该命令的压缩手册页。
  1. 你可以过滤结果以仅显示特定类型的文件。要仅查看与 passwd 关联的二进制文件,请使用 -b(binary)标志。
whereis -b passwd

这将输出范围缩小到仅可执行文件和相关文件,排除了手册页。

passwd: /usr/bin/passwd /etc/passwd
  1. 同样,要仅查找手册页,请使用 -m(manual)标志。当你只想知道某个命令有哪些可用文档时,这非常有用。
whereis -m passwd

输出现在仅列出手册页位置。

passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
  1. 了解 whereis 的局限性很重要。它只搜索标准的系统目录。让我们尝试查找我们在 find_lab 目录中创建的 report.txt 文件。
whereis report.txt

该命令仅返回文件名,没有路径:

report.txt:

这是因为 report.txt 位于你的主目录(~/project/find_lab)中,而该目录不是系统二进制文件或手册页的标准存放位置。这展示了关键区别:对于个人或项目文件,请使用 findlocate;而要调查系统命令,请使用 whereis

你现在已经学习了如何使用 whereis 快速定位组成 Linux 命令的文件,这是系统管理和故障排除中的一项实用技能。

使用 aliaswhichtype 分析命令路径

在最后一步中,我们将探索 Shell 在你输入命令名称时如何确定执行哪个命令。这并不总是像在磁盘上查找文件那么简单。Shell 有一套特定的优先级顺序:它首先检查 别名(alias),然后是 Shell 内置命令,最后在系统的 $PATH 环境变量所列出的目录中搜索可执行文件。你将学习使用 alias 创建命令快捷方式,并使用 whichtype 来诊断命令名称实际指向的内容。

让我们首先创建一个临时别名,看看它如何影响命令执行。我们将留在 ~/project 目录中。

  1. 别名是用户定义的另一个命令的快捷方式。让我们创建一个别名,使 pwd 命令(打印工作目录)改为执行 date 命令。
alias pwd='date'
  1. 现在,执行 pwd 命令。
pwd

它没有打印当前目录,而是打印了当前的日期和时间,因为别名的优先级更高。

<当前日期和时间>

使用 whichtype 进行调查

现在,假设你不知道这个别名的存在。你该如何排查为什么 pwd 表现异常?这就是 whichtype 的用武之地。

  1. which 命令在 $PATH 环境变量列出的目录中定位可执行文件。
which pwd

输出将显示:

pwd: aliased to date
  1. type 命令更为全面。它是一个 Shell 内置命令,用于描述 Shell 将如何解释某个命令名称,包括别名和内置函数。
type pwd

此命令准确地识别了情况:

pwd is an alias for date
  1. 要查看与名称匹配的所有可能命令,可以使用 -a(all)标志。这与 type 配合使用时非常强大。
type -a pwd

这揭示了 pwd 命令名称的完整层级结构:

pwd is an alias for date
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd

此输出告诉了你 Shell 的优先级顺序:它会首先使用别名。如果别名不存在,它将使用 Shell 内置的 pwd 命令。如果这两者都不存在,它将执行位于 /usr/bin/pwd 的程序。

删除别名

最后,让我们通过删除别名来清理实验环境。

  1. unalias 命令从当前 Shell 会话中删除别名定义。
unalias pwd
  1. 现在,再次运行 pwdtype pwd 以确认一切恢复正常。
pwd

输出:

/home/labex/project
type pwd

输出:

pwd is a shell builtin

你现在已经学习了如何创建和删除别名,更重要的是,学会了如何使用 whichtype 来准确理解 Shell 将运行哪个命令。

总结

在本实验中,你学习了如何在 Linux 文件系统中搜索文件和目录。你从功能强大的 find 命令开始,使用基于名称的条件和通配符进行基础搜索,然后进阶到使用 -execxargs 对搜索结果执行命令。你还探索了 locate 命令,作为一种基于数据库的更快速的替代方案,并学习了如何使用 updatedb 维护其数据库。

此外,本实验还涵盖了定位和分析命令的技术。你使用了 whereis 来查找命令二进制文件及其手册页的位置。为了理解命令执行路径,你学习了使用 which 来识别被调用的具体可执行文件,以及使用 type 来确定命令是别名、内置命令还是文件,同时还分析了别名如何影响命令行为。