在 Linux 中管理文件与目录

CompTIABeginner
立即练习

介绍

在本实验中,你将学习在 Linux 命令行环境中管理文件和目录的基础技能。你将通过实践获得使用 mkdirrm 创建及删除复杂目录结构的经验,并学习使用 cpmv 复制及移动文件和目录。

此外,本实验还提供了对文件链接(Linking)的深入探索。你将使用 ln 命令创建符号链接(软链接)和硬链接,分析底层的索引节点(inode)概念,并观察当源文件被修改时,每种链接类型所表现出的不同行为。这将帮助你更深入地理解 Linux 文件系统是如何组织和引用数据的。

这是一个引导实验,提供分步指令以帮助你学习和练习。请仔细遵循说明完成每个步骤并获得实践经验。历史数据表明,这是一个初学者级别的实验,完成率为 93%。它在学习者中获得了 99% 的好评率。

使用 mkdir、rmdir 和 rm 创建与删除目录结构

在这一步中,你将学习如何创建和删除目录。将文件组织到目录的分层结构中是 Linux 中的一项基本任务。我们将使用 mkdir 命令创建目录,使用 rmdir 删除空目录,以及使用 rm 删除目录及其所有内容。所有命令都将在你的默认目录 ~/project 中执行。

首先,让我们创建一个简单的目录。mkdir 命令代表「make directory」(创建目录)。

在终端中执行以下命令来创建一个名为 cars 的目录:

mkdir cars

要验证目录是否已创建,可以使用 ls -ld 命令。-l 选项提供长列表格式,-d 选项仅列出目录条目本身,而不是其内容。

ls -ld cars

你应该会看到类似下面的输出,确认 cars 目录已创建。权限字符串开头的 d 表示这是一个目录。

drwxr-xr-x 2 labex labex 4096 May 20 10:30 cars

现在,让我们删除这个目录。rmdir 命令用于删除「空」目录。

rmdir cars

再次运行 ls -ld 命令验证其是否已被删除。

ls -ld cars

这一次,你会收到一条错误消息,因为该目录已不存在。这证明 rmdir 执行成功。

ls: cannot access 'cars': No such file or directory

rmdir 命令仅适用于空目录。如果我们有一个嵌套的目录结构该怎么办?让我们尝试创建一个目录结构 pastry/pies/cakes。为了根据需要创建父目录,我们必须在 mkdir 中使用 -p(parents)选项。

执行以下命令:

mkdir -p pastry/pies/cakes

要查看刚刚创建的整个目录结构,请使用带有 -l(长格式)和 -R(递归)选项的 ls 命令。

ls -lR pastry

输出将显示 pastry 目录及其子目录 piescakes

pastry:
total 4
drwxr-xr-x 3 labex labex 4096 May 20 10:35 pies

pastry/pies:
total 4
drwxr-xr-x 2 labex labex 4096 May 20 10:35 cakes

pastry/pies/cakes:
total 0

现在,让我们尝试使用 rmdir 删除 pastry 目录。

rmdir pastry

为什么这个命令失败了?终端会显示一条错误消息:

rmdir: failed to remove 'pastry': Directory not empty

这是因为 rmdir 只能删除空目录,而 pastry 包含了 pies 子目录。

要删除一个目录及其所有内容(包括子目录和文件),必须使用带有 -r(递归)选项的 rm 命令。请务必小心使用此命令,因为它会永久删除数据。

rm -r pastry

如果执行成功,该命令不会产生任何输出。你可以通过再次运行 ls -ld pastry 来验证 pastry 目录是否已被完全删除,这应该会导致「No such file or directory」错误。

ls -ld pastry

使用 vi 和 ln -s 创建文件和符号链接

在这一步中,你将使用 vi 文本编辑器创建一个文件,然后为其创建一个符号链接。符号链接(Symbolic link),也称为软链接(Soft link),是一种特殊类型的文件,它指向另一个文件或目录。它类似于其他操作系统中的「快捷方式」。

首先,让我们使用 vi 创建一个名为 filea 的简单文本文件。vi 是一个功能强大的屏幕文本编辑器。它有两种主要模式:命令模式(Command mode)和插入模式(Insert mode)。启动时处于命令模式,此时按键被解释为命令。要输入文本,必须进入插入模式。

  1. 在终端中(路径应为 ~/project),启动 vi 以创建文件 filea
vi filea
  1. 终端现在将显示 vi 编辑器界面。要开始输入,需要切换到插入模式。按一次 i 键。你可能会在屏幕底部看到 -- INSERT -- 字样。
  2. 现在,输入以下文本:
This is filea.
  1. 要保存文件并退出 vi,必须先按 Esc 键返回命令模式。然后,输入 ZZ(按住 Shift 并连按两次 Z)。此命令将保存文件并退出编辑器。

现在回到命令提示符,让我们验证文件是否已创建且内容正确。

首先,列出文件:

ls filea

输出应仅为文件名:

filea

接下来,使用 cat 命令显示其内容:

cat filea

输出应与你输入的文本一致:

This is filea.

现在,让我们创建一个符号链接。我们将创建一个名为 fileb 的链接,指向我们的原始文件 filea。命令格式为 ln -s <源文件> <目标链接>

ln -s filea fileb

要测试结果,请使用 ls -il 命令。-i 选项显示索引节点(inode)编号,它是文件系统上文件或目录的唯一标识符。

ls -il file[ab]

仔细检查输出。

131075 -rw-r--r-- 1 labex labex 14 May 20 10:40 filea
131076 lrwxrwxrwx 1 labex labex  5 May 20 10:41 fileb -> filea

请注意几个关键点:

  • 文件类型filea 的权限字符串以 - 开头,表示一个普通文件。fileb 的字符串以 l 开头,表示一个符号链接。
  • 链接指针:输出清晰地显示了 fileb -> filea
  • Inode 编号:查看第一列。fileafileb 的 inode 编号是不同的。为什么?因为符号链接是一个独立的文件,它只是存储了目标文件的路径。它本身不是那个文件,因此拥有自己唯一的 inode。

最后,让我们看看是否可以通过链接读取内容。

cat fileb

输出是 filea 的内容:

This is filea.

这是预期行为。当你对符号链接执行 cat 之类的操作时,系统会自动跟随链接找到源文件并对其执行操作。

使用 ln 和 Inode 创建并分析硬链接

在这一步中,你将创建一个硬链接(Hard link),并了解它与之前创建的符号链接有何不同。符号链接是指向文件名的指针,而硬链接则是文件本身的另一个名称。两个名称都直接指向磁盘上的同一块数据,这块数据由一个称为 inode 的唯一编号标识。

我们将继续在 ~/project 目录中使用上一步中的文件 fileafileb

首先,让我们创建一个名为 filec 的硬链接,使其指向与 filea 相同的 inode。为此,我们使用不带 -s 选项的 ln 命令。

ln filea filec

现在,让我们查看所有三个文件的内容:原始文件 filea、符号链接 fileb 以及新的硬链接 filec

cat filea
cat fileb
cat filec

你会看到相同的内容被打印了三次,这是预料之中的。

This is filea.
This is filea.
This is filea.

当我们检查文件属性时,真正的区别就显现出来了。再次使用 ls -il 命令查看所有三个文件的 inode 编号和其他详细信息。

ls -il file[a-c]

输出将类似于这样。请密切注意第一列和第二列。

131075 -rw-r--r-- 2 labex labex 14 May 20 10:40 filea
131076 lrwxrwxrwx 1 labex labex  5 May 20 10:41 fileb -> filea
131075 -rw-r--r-- 2 labex labex 14 May 20 10:40 filec

让我们分析一下这个输出:

  • Inode 编号(第 1 列):注意 fileafilec 具有完全相同的 inode 编号(例如 131075)。这是硬链接的定义特征。它们不是独立的文件;它们是指向磁盘上相同文件数据的两个不同名称。而符号链接 fileb 拥有自己唯一的 inode。
  • 链接计数(第 2 列):查看 fileafilec 的数字。它现在是 2。这个数字是硬链接计数,它跟踪有多少个名称(硬链接)指向这个单一的 inode。当你创建 filec 时,该 inode 的链接计数从 1 增加到了 2。
  • 文件类型(权限字符串的第 1 位):注意 filec 被列为普通文件(其权限以 - 开头),就像 filea 一样。它不是像 fileb(以 l 开头)那样的特殊链接类型。

观察修改源文件后的链接行为

在这一步中,你将观察当原始源文件被删除并重新创建时,符号链接和硬链接在行为上的关键差异。这将巩固你对每种链接工作原理的理解。我们将继续在 ~/project 目录中使用 fileafilebfilec

首先,让我们删除原始文件 filea

rm filea

现在,让我们检查这三个文件的状态。使用 ls -l 命令。由于 filea 已不存在,你可能会看到关于它的错误,这是正常的。

ls -l file[a-c]

输出将非常有启发性:

ls: cannot access 'filea': No such file or directory
lrwxrwxrwx 1 labex labex 5 May 20 10:41 fileb -> filea
-rw-r--r-- 1 labex labex 14 May 20 10:40 filec
  • 符号链接 fileb:链接现在「断开了」。它仍然指向名称 filea,但该名称不再对应任何现有文件。在许多终端中,文件名 fileb 会显示为红色以指示这种断开状态。如果你尝试 cat fileb,将会报错。
  • 硬链接 filec:文件 filec 完全不受影响。它的链接计数(第二列)只是从 2 减少到了 1,但文件及其数据依然完好无损。这是因为删除 filea 只是删除了指向该 inode 的其中一个名称;直到链接计数降为零,数据才会被删除。你可以通过查看其内容来证明这一点:
cat filec

输出仍然是原始内容:

This is filea.

现在,让我们重新创建 filea,但使用不同的内容。使用 vi 创建一个名为 filea 的新文件。

  1. 启动 vivi filea
  2. i 进入插入模式。
  3. 输入新内容:This is the new filea.
  4. Esc 返回命令模式,然后输入 ZZ 保存并退出。

有了新的 filea 后,让我们再次使用 ls -il 检查这三个文件。

ls -il file[a-c]

输出将显示一种新情况:

131080 -rw-r--r-- 1 labex labex 20 May 20 11:05 filea
131076 lrwxrwxrwx 1 labex labex  5 May 20 10:41 fileb -> filea
131075 -rw-r--r-- 1 labex labex 14 May 20 10:40 filec
  • 新的 filea:一个新的 filea 文件存在了,但请注意它的 inode 编号(例如 131080)与 filec 的 inode(例如 131075)是不同的。这是一个全新的文件,只是恰好与旧文件同名。
  • 符号链接 fileb:链接不再断开!它自动指向了名为 filea 的新文件。
  • 硬链接 filecfilec 保持不变。它仍然指向原始的 inode 并包含原始数据。

最后,让我们检查所有三个文件的内容以查看结果。

cat filea
cat fileb
cat filec

输出清晰地展示了区别:

This is the new filea.
This is the new filea.
This is filea.

符号链接 fileb 跟随名称找到了新文件,而硬链接 filec 则维持了与原始数据的连接。

使用 cp 和 mv 复制与移动文件

在最后一步中,你将学习使用 cp(复制)和 mv(移动)命令,它们是管理文件的核心工具。cp 命令创建文件或目录的副本,而 mv 命令则用于重命名文件/目录或将其移动到不同位置。

首先,让我们清理之前步骤中的文件,以获得一个干净的工作空间。所有命令都将在 ~/project 目录中运行。

rm filea fileb filec

使用 cp 复制文件

cp 命令会创建一个新的、独立的副本。新文件将拥有自己的 inode。

  1. 首先,使用 touch 命令创建一个简单的文件。如果文件不存在,touch 会创建一个空文件。
touch source_file
  1. 现在,查看其属性,注意 inode 编号(第一列)。
ls -i source_file

输出将显示该文件的唯一 inode 编号。

131081 source_file
  1. 接下来,将 source_file 复制到一个名为 copied_file 的新文件。
cp source_file copied_file
  1. 现在,列出这两个文件的属性。
ls -i source_file copied_file

你会看到它们是两个独立的文件,具有不同的 inode 编号。

131082 copied_file
131081 source_file

使用 mv 移动和重命名文件

mv 命令非常多才。如果目标是同一目录下的新文件名,它会重命名文件。如果目标是一个目录,它会将文件移动到该目录中。当在同一个文件系统内重命名或移动文件时,inode 编号不会改变;该命令只是更新了文件的名称或位置指针。

  1. 让我们将 source_file 重命名为 renamed_file
mv source_file renamed_file
  1. 检查新命名文件的 inode。
ls -i renamed_file

你会注意到 inode 编号(例如 131081)与原始的 source_file 相同。文件本身没有改变,改变的只是它的名字。

131081 renamed_file
  1. 现在,让我们移动这个文件。首先,创建一个目标目录。
mkdir move_destination
  1. renamed_file 移动到 move_destination 目录中。
mv renamed_file move_destination/
  1. 验证文件现在是否在目录内,并再次检查其 inode。
ls -i move_destination/renamed_file

inode 编号保持不变,确认文件是被移动了,而不是被复制。

131081 move_destination/renamed_file

处理覆盖操作

默认情况下,许多系统将 cp 别名为 cp -i,以防止你意外覆盖现有文件。-i 代表「interactive」(交互式)。

  1. 让我们尝试将 copied_file 复制并覆盖 move_destination 目录内的文件。
cp -i copied_file move_destination/renamed_file
  1. 由于 -i 别名的存在,系统会提示你确认。
cp: overwrite 'move_destination/renamed_file'?

输入 y 并按回车键确认覆盖。如果你想取消,可以输入 n

总结

在本实验中,你学习了在 Linux 环境中管理文件和目录的基本命令。你练习了使用 mkdir 创建目录结构(包括用于创建父目录的 -p 选项),并学习了使用 rmdir 删除空目录以及使用 rm 删除非空目录。你还使用 vi 编辑器创建了文件,并初步了解了文件链接的概念。

实验的核心在于创建和分析两种类型的链接:使用 ln -s 创建的符号链接(软链接)和使用 ln 创建的硬链接。通过检查 inode 并观察当源文件被修改或删除时每种链接的表现,你掌握了它们之间的关键区别。最后,你使用 cp 命令创建了文件的独立副本,并使用 mv 命令移动或重命名了文件和目录,完成了对基本文件管理操作的全面学习。