简介
想象一下,你每天都给一株不断长大的植物拍一张照片。如果每张照片都命名为 plant.jpg,新照片就会不断覆盖旧照片,你也会丢失历史记录。要保留所有照片,就需要将它们命名为 plant_2023-01-01.jpg、plant_2023-01-02.jpg 等。
系统备份也存在同样的问题。如果始终写入同一个文件名,每次新的备份都可能覆盖上一次备份,导致恢复历史丢失。
在本实验中,你将学习如何自动完成这种命名过程。带时间戳的备份是实际工作中非常常见的做法,因为只有能够判断备份创建时间并保留多个版本,备份文件才真正有用。
你将学习:
- 让 Linux 按指定格式显示今天的日期。
- 将日期存储在一个「盒子」中,也就是变量。
- 使用这个日期创建唯一的、带时间戳的备份文件。
获取今天的日期
在这一步中,你将学习如何使用 date 命令格式化当前日期。这是创建动态文件名的第一步。
标准的 date 命令会以较长的文字格式显示当前日期和时间。但对于文件名,我们通常需要类似 YYYY-MM-DD 的简洁格式,这种格式也便于排序。Linux 允许你使用 + 符号和格式代码自定义输出。%F 是「完整日期」(年 - 月 - 日)的便捷缩写。
这种格式不只是美观,也很实用:使用 YYYY-MM-DD 时,按字母顺序排序的文件名也会按时间先后顺序排列。
首先,确认当前位于项目目录:
cd ~/project
现在,让系统按我们需要的格式显示日期:
date +%F
你应该会看到类似 2023-10-27 的输出,但实际日期应为今天的日期。
要将这个结果用于文件名,我们需要先捕获它。可以使用命令替换来完成。你可以把它理解为将命令放进 $(...) 这个「气泡」中。Shell 会先执行气泡中的命令,获取命令结果,然后用这段文本替换整个气泡。
命令替换是 Shell 的核心概念之一,它开始将简单的命令行操作与自动化联系起来。它可以将一个命令的输出作为另一个命令的数据。
现在,将这个日期存储到一个变量中。变量就是一个有名称的存储盒。我们将创建名为 current_date 的盒子,并把命令输出放进去。
current_date=$(date +%F)
重要提示:注意,= 符号两边不能有空格。这是 Shell 的严格规则。variable = value 会失败,而 variable=value 才能正常工作。
现在,查看盒子中的内容,确认日期已经存储进去。使用 echo 命令,并在变量名前加上 $ 符号,就可以「打开」这个盒子:
echo $current_date
如果输出的是今天的日期,就说明你已经成功捕获了日期!
创建备份文件
现在日期已经存储在变量中,我们可以使用它创建一个含义清晰的备份文件名。
我们已经在你的目录中准备好了一个名为 project_plan.txt 的文件。确认该文件存在:
ls -l project_plan.txt
我们的目标是创建该文件的副本,并将副本命名为 project_plan_YYYY-MM-DD.bak。这样,副本的文件名就带有当天的日期。
我们将使用标准的 cp(复制)命令。但不需要手动输入日期,而是让 Shell 使用变量 $current_date 自动插入日期。
运行以下命令:
cp project_plan.txt "project_plan_$current_date.bak"
Shell 会看到双引号中的 $current_date,并在执行复制命令之前,立即将它替换为变量中存储的实际日期,例如 2023-10-27。
这称为变量展开。Shell 会在真正启动 cp 命令之前展开变量,因此即使 cp 本身并不理解 Shell 变量,这条命令仍然可以动态生成文件名。
实用提示:你也可以跳过变量这一步,将所有操作写在一行中!这种写法在自动化脚本中非常常见。直接将 $(...) 这个命令替换结构放入 cp 命令:
cp project_plan.txt "project_plan_$(date +%F).bak"
这条命令告诉 Shell:「运行 date 命令,将结果粘贴到这里,然后运行复制命令。」两种方法得到的结果完全相同。
验证备份
现在确认备份是否创建成功。此时应该能看到两个文件:原始文件和带时间戳的副本。
列出目录中的文件:
ls -l
你应该会看到类似以下内容:
-rw-rw-r-- 1 labex labex 65 Oct 27 10:00 project_plan.txt
-rw-rw-r-- 1 labex labex 65 Oct 27 10:05 project_plan_2023-10-27.bak
注意,新文件的名称中包含了日期。
最后,确认副本中的内容没有问题。可以使用 cat 命令读取新文件。由于我们可能不想再次手动输入完整日期,因此可以再次使用命令替换:
cat project_plan_$(date +%F).bak
你应该会看到原始文本:
Phase 1: Initialization
Phase 2: Development
Phase 3: Deployment
成功!你已经创建了一个带时间戳的备份。如果明天运行同样的命令,它会创建一个使用明天日期的新文件,从而安全、有序地保留历史记录。
这种简单的命名习惯可以应用到更复杂的场景中。许多备份轮换方案正是从这个思路开始的:将时间编码到文件名中,这样就能保留多个版本,而不是覆盖最新的副本。
总结
恭喜!你已经掌握了一项重要的自动化技能。
在本实验中,你学习了:
- 格式化时间:使用
date +%F获取适合计算机处理的日期字符串。 - 命令替换:使用
$(...)将一个命令的结果传递给另一个命令。 - 动态命名:创建根据当前日期自动命名的文件。
这个看似简单的技巧是专业备份策略的基础。现在,你可以避免文件被意外覆盖了!



