在Linux中计算目录的MD5校验
1. 简介
在我们日常使用 Linux 的过程中,我们可能想要检查目录中的任何文件是否发生了变化。或者我们可能想确认一个目录的内容与不同位置、磁盘或系统中的另一个目录相同。
在本教程中,我们将学习如何在 Linux 中计算整个目录树的MD5校验 。我们将计算目录所有内容的单个哈希值以进行比较。
2. 获取目录树中所有文件的列表
**要找出目录树中所有文件的集体哈希,我们应该首先获取这些文件的列表。*我们将使用find *命令来完成此任务。
让我们运行tree 命令来查看我们的示例目录结构:
$ tree
.
├── file1.png
├── folder1
│ ├── file2.jpg
│ └── folder3
│ └── file3.txt
└── folder2
└── file4.sh
如我们所见,我们在多个子目录中有文件。我们现在可以使用带有*-type f参数的find*命令来获取目录及其子目录中所有文件的列表,不包括文件夹和符号链接:
$ find . -type f
./folder2/file4.sh
./folder1/folder3/file3.txt
./folder1/file2.jpg
./file1.png
现在,我们可以通过运行单个命令来获取目录及其子目录中所有文件的列表。
3. 使用sort和“语言环境问题”进行排序
现在我们可以获得所有文件的列表,接下来的步骤是:
- 对该列表中的每个文件运行md5sum 命令
- 创建一个包含文件路径列表及其哈希值的字符串
- 最后,在我们刚刚创建的这个字符串上运行md5sum以获得单个哈希值
因此,如果我们目录中的任何内容发生变化,包括文件路径或文件列表,哈希值也会发生变化。但是我们对这种方法有一个问题。
** find命令默认不对其输出进行排序。**出于效率目的,find命令只打印它在遍历文件系统时获得的各个结果。所以顺序可以在不同的系统、位置甚至不同的运行之间改变。因此,即使两个目录完全相同,哈希值也会发生变化。
我们可以通过使用sort 命令对搜索结果进行排序来解决这个问题:
$ find . -type f | sort
./file1.png
./folder1/file2.jpg
./folder1/folder3/file3.txt
./folder2/file4.sh
但是我们仍然缺少一些东西。
排序操作比看起来更复杂。字母、数字、日期以及它们的排序方式会因地区而异。这可以改变我们对位于具有不同区域设置的两个系统上的目录的结果。我们可以通过使用LC_ALL 环境变量覆盖我们的语言环境来解决这个问题:
$ find . -type f | LC_ALL=C sort
./file1.png
./folder1/file2.jpg
./folder1/folder3/file3.txt
./folder2/file4.sh
通过使用标准 C 语言环境进行排序操作,我们消除了排序问题。
4. 把它们放在一起
我们可以使用find命令的-exec参数对找到的每个文件执行md5sum*命令:*
$ find . -type f -exec md5sum {} +
7d2186aaeed78b24f00f782f2346e5f9 ./folder2/file4.sh
d41d8cd98f00b204e9800998ecf8427e ./folder1/folder3/file3.txt
c6aa7ce9967680b77ea7e72d96949303 ./folder1/file2.jpg
46ffe26d56fe5164570ad43cc79b59d3 ./file1.png
我们使用花括号 ( {} ) 来指定将文件名作为参数传递给md5sum命令的位置。
此外,我们在末尾添加了加号 ( + ),因此我们的文件将作为参数传递给单个md5sum命令 ( md5sum file1 file2 file3..) ,而不是为每个文件运行单独的md5sum进程。请注意,选择一种或另一种方法不会改变输出的格式。
执行上述命令后,我们需要在计算最终的 MD5 哈希值之前对输出进行排序:
$ find . -type f -exec md5sum {} + | LC_ALL=C sort
46ffe26d56fe5164570ad43cc79b59d3 ./file1.png
7d2186aaeed78b24f00f782f2346e5f9 ./folder2/file4.sh
c6aa7ce9967680b77ea7e72d96949303 ./folder1/file2.jpg
d41d8cd98f00b204e9800998ecf8427e ./folder1/folder3/file3.txt
正如我们所看到的,现在我们已经对所有文件的哈希值进行了排序,并准备好进行最终的哈希计算。 然后让我们添加最终的命令管道:
$ find . -type f -exec md5sum {} + | LC_ALL=C sort | md5sum
8b0d2ca740c06ea8ab2619f14e75b652 -
这是我们对目录的最终哈希值。请注意,我们仅通过考虑文件内容和文件路径来计算此值。我们故意忽略了其他文件属性,例如修改日期、权限或所有者,没有将它们包括在我们的列表中。
5. 考虑文件属性
假设我们还想在计算哈希值时包含每个文件的修改日期。 让我们首先定义一个要在每个文件名上运行的函数:
summary (){
echo "$(stat -c '%y' "$1") $(md5sum "$1")"
}
我们可以使用此函数打印修改日期、校验和和文件名。让我们将其导出并与find命令一起使用:
$ export -f summary
最后,让我们通过在找到的每个文件上运行我们的命令来将它们放在一起:
$ find . -type f -exec bash -c 'summary "$0"' {} \; | LC_ALL=C sort | md5sum