我正在编写一个 shell 脚本,它使用
shasum
检查目录的内容是否已更改。
在 Linux 和 FreeBSD 上,当我执行
shasum
时,shasum <directory>
具有相同的行为,但是,在 MacOS 上,shasum
只为我提供文件的哈希值。
FreeBSD
$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa CONTENTS/
Linux
$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa CONTENTS/
MacOS
$ shasum CONTENTS/
shasum: CONTENTS/:
如何计算 MacOS 中目录的哈希值?
尝试 1:将 TAR 与管道一起使用
尝试使用,但似乎这个 tar 选项在 MacOS 上不起作用。
tar cO CONTENTS/ | shasum
tar: Option -O is not permitted in mode -c
da39a3ee5e6b4b0d3255bfef95601890afd80709 -
尝试 2:使用 FIND/EXEC
MacOS 和 FreeBSD 之间是一致的,但 Linux 返回了一个奇怪的哈希值
find CONTENTS -type f -exec shasum {} \; | sort -k 2 | shasum
Linux
c2ddb9bc5f543e956f5cdcc76750cb78cc5f26f3
FreeBSD
3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824
MacOS
3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824
关于焦油的其他发现
tar
会非常好,因为它“归档”一个文件夹,然后我可以
shasum
它,但是
tar
“行走”文件夹结构的顺序在不同操作系统 中不一致。正如一些帮助者在评论中提到的,我应该在所有系统中使用相同版本的
tar
。举个例子,在系统1上我有这个命令:
drwxr-xr-x 0 root wheel 0 27 Jul 07:23 usr/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/f0/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/aaa
在系统 2 上我有以下命令:
drwxr-xr-x 0 root wheel 0 27 Jul 07:23 usr/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/aaa
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/aaa
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/f0/aaa
从
tar
的角度来看,如果一切都很好,但由于顺序,
shasum
会产生不同的哈希值。
结论
shasum
在 Linux 和 BSD 中检查单个文件哈希是一致的,但是,当涉及到目录时,一致性仅发生在 MacOS 和 FreeBSD 上,可能是由于文件的排序方式所致。如果使用
find
命令强制排序,则仅在 FreeBSD 和 MacOS 中获得一致性,但是此方法的时间限制,因为它需要大量时间来计算每个文件的哈希值,然后计算整个结构哈希值。使用
tar
创建临时文件,然后执行
shasum
也发现Linux和BSD之间不一致,可能是因为归档方法的不同。我认为唯一的出路是
重新设计我的解决方案。
$ mkdir -p test
$ echo 1 > test/tmp
$ tar cO test/ | md5sum
7b18a99a8ccfef1ebbfd1e7a8b2852ee
$ echo 2 > test/tmp
$ tar cO test/ | md5sum
644042dd530157e604641ea89b4e9152
请注意,如果您将相同的内容写入文件,
modified
统计信息将更新,并且将为该目录生成新的哈希值。
$ echo 2 > test/tmp
$ tar cO test/ | md5sum
da25819594f123563a837d5786e51950 -
$ echo 2 > test/tmp
$ tar cO test/ | md5sum
9407b64d43b809a5828a9fc2297b4e9c -
附注你应该将
md5sum
更改为
shasum
:-)
编辑:
与一位使用 MacOSX 的朋友进行了短暂讨论,他想出了:
$ mkdir tmp; echo 1 > test/a;
$ tar -cf - tmp/ | md5sum
26c43adc9eca9f63279d08a0d145dd7d -
$ echo 2 > test/a
$ tar -cf - tmp/ | md5sum
dc3a68cac0b0224be9b202d86e69c5bd -
请注意,MACosx 使用
md5
而不是
md5sum
。