md5sum程序不提供目录的校验和。我想为目录的整个内容(包括子目录中的文件)获取一个MD5校验和。也就是说,从所有文件中得出一个组合的校验和。有办法吗?

#1 楼

正确的方法取决于您要问的原因:

选项1:仅比较数据

如果只需要散列树的文件内容,则可以技巧:

$ find -s somedir -type f -exec md5sum {} \; | md5sum


这首先以可预测的顺序分别总结了所有文件内容,然后传递该文件名列表和MD5哈希表以对其自身进行哈希处理

不幸的是,find -s仅适用于macOS,FreeBSD,NetBSD和OpenBSD中使用的BSD find(1)。为了在具有GNU或SUS find(1)的系统上获得可比的性能,您需要一些更丑陋的功能:


find -s添加呼叫。 sort位告诉它跳过MD5哈希,因此它仅按-k 2的估算对文件名进行排序,这些文件名位于行尾2字段中。命令的版本,即如果您在文件名中包含换行符,则很可能会感到困惑,因为它看起来像sort调用的多行。 sort变体不存在此问题,因为树遍历和排序发生在同一个程序find -s中。在任何一种情况下,都必须进行排序以避免误报:最常见的Unix Linux文件系统不能以稳定,可预测的顺序维护目录列表。您可能不会通过使用find等来实现此目的,后者会为您静默地对目录内容进行排序。调用ls而不以某种方式对其输出进行排序将导致输出中的行顺序与基础文件系统返回的行顺序相匹配,如果作为输入而分配给它的文件顺序发生变化,这将导致此命令给出更改的哈希值,即使数据保持相同。

您可能会问,上面的GNU find命令中的-k 2位是否必要。只要文件内容的哈希值足以代替文件名,只要内容没有更改,就可以删除该选项,不会出现误报,允许我们对GNU和BSD使用同一命令。但是,请注意,如果存在哈希冲突,则文件名的确切顺序与不使用sort进行操作时可以给出的部分顺序不匹配的可能性很小(MD5为1:2128)。但是请记住,如果与应用程序发生不匹配的可能性很小,那么整个方法可能就不适合您了。

您可能需要将sort命令更改为-k 2或某些其他哈希函数。如果您选择另一个哈希函数,并且需要系统的第二种形式的命令,则可能需要相应地调整md5sum命令。另一个陷阱是某些数据求和程序根本不会写出文件名,一个典型的例子是旧的Unix md5程序。其中N是树中文件的数量,但这是避免哈希文件和目录元数据的必要成本。

选项2:比较数据和元数据

如果需要为了能够检测到树中的任何内容都发生了变化,而不仅仅是文件内容发生了变化,请让sort为您打包目录内容,然后将其发送给sum

$ find somedir -type f -exec md5sum {} \; | sort -k 2 | md5sum


因为md5sum还可以看到文件的权限,所有权等,所以它还可以检测到对这些内容的更改,而不仅是对文件内容的更改。

此方法要快得多,因为它只能通过一次在树上运行,并且仅运行一次哈希程序。

与上述基于tar的方法一样,md5sum将按照基础文件系统返回它们的顺序来处理文件名。很有可能在您的应用程序中,您可以确定不会导致这种情况发生。我可以想到至少有三种不同的使用模式。 (我不会列出它们,因为我们正在进入未指定的行为领域。每个文件系统在这里都可以不同,甚至从一个版本的操作系统到另一个版本也可以不同。)自己会得到误报,建议您在Gilles的答案中使用tar选项。

评论


我认为最好导航到要比较的目录并使用find。而不是找到somedir。这样,在提供不同的路径规范时,文件名是相同的。这可能很棘手:-)

–阿巴菲
2014年6月24日6:50



我们也应该对文件排序吗?

– CMCDragonkai
16年1月19日,下午2:52

@CMCDragonkai:你是什么意思?在第一种情况下,我们会对文件名列表进行排序。在第二种情况下,我们故意不这样做,因为第一句中强调的部分内容是目录中文件的顺序已更改,因此您不想对任何内容进行排序。

–沃伦·杨(Warren Young)
16年1月19日,下午3:45

@WarrenYoung您能否更彻底地解释为什么选项2并不总是更好?它似乎更快,更简单并且更具跨平台性。在哪种情况下不应该是选项1?

–罗宾·温斯洛(Robin Winslow)
16年8月17日在7:51

选项1的替代方法:找到somedir -type f -exec sh -c“ openssl dgst -sha1 -binary {} | xxd -p” \; |排序openssl dgst -sha1忽略所有文件名(应使用换行符)

–windm
17-10-22在9:50

#2 楼

校验和必须是文件的确定性和明确表示形式。确定性意味着,如果将相同的文件放在相同的位置,则会得到相同的结果。明确意味着两个不同的文件集具有不同的表示形式。

数据和元数据

创建包含这些文件的存档是一个好的开始。这是明确的表示形式(显然,因为您可以通过提取存档来恢复文件)。它可能包含文件元数据,例如日期和所有权。但是,这还不太正确:档案文件模棱两可,因为其表示形式取决于文件的存储顺序,并且如果适用,还取决于压缩。归档之前先保存文件名。如果文件名不包含换行符,则可以运行find | sort列出换行符,然后按此顺序将它们添加到存档中。注意告诉存档器不要递归到目录中。以下是POSIX pax,GNU tar和cpio的示例:

 find | LC_ALL=C sort | pax -w -d | md5sum
find | LC_ALL=C sort | tar -cf - -T - --no-recursion | md5sum
find | LC_ALL=C sort | cpio -o | md5sum
 


仅名称和内容,这是技术含量较低的方法

如果您只想考虑文件数据而不考虑元数据,则可以创建仅包含文件内容的存档,但是没有标准工具。除了包含文件内容之外,还可以包含文件的哈希。如果文件名不包含换行符,并且仅包含常规文件和目录(没有符号链接或特殊文件),则这很容易,但是您需要注意一些事项:

 { export LC_ALL=C;
  find -type f -exec wc -c {} \; | sort; echo;
  find -type f -exec md5sum {} + | sort; echo;
  find . -type d | sort; find . -type d | sort | md5sum;
} | md5sum
 


除了校验和列表之外,我们还包括一个目录列表,否则将看不到空目录。文件列表已排序(在特定的,可复制的语言环境中-感谢Peter.O提醒我这一点)。 echo将这两部分分开(没有这个,您可以创建一些空目录,其名称看起来像md5sum输出,也可以传递普通文件)。我们还提供了文件大小列表,以避免长度扩展攻击。

不建议使用MD5。如果可用,请考虑使用SHA-2,或至少使用SHA-1。

名称和数据,在名称中支持换行符

这是上面代码的一种变体依靠GNU工具将文件名分隔为空字节。这允许文件名包含换行符。 GNU摘要实用程序在其输出中引用特殊字符,因此不会出现歧义的换行符。

 
一种更强大的方法

这是一个经过最低程度测试的Python脚本,该脚本构建描述文件层次结构的哈希。它考虑目录和文件内容,并忽略符号链接和其他文件,如果无法读取任何文件,则返回致命错误。

 { export LC_ALL=C;
  du -0ab | sort -z; # file lengths, including directories (with length 0)
  echo | tr '\n' '#! /usr/bin/env python
import hashlib, hmac, os, stat, sys
## Return the hash of the contents of the specified file, as a hex string
def file_hash(name):
    f = open(name)
    h = hashlib.sha256()
    while True:
        buf = f.read(16384)
        if len(buf) == 0: break
        h.update(buf)
    f.close()
    return h.hexdigest()
## Traverse the specified path and update the hash with a description of its
## name and contents
def traverse(h, path):
    rs = os.lstat(path)
    quoted_name = repr(path)
    if stat.S_ISDIR(rs.st_mode):
        h.update('dir ' + quoted_name + '\n')
        for entry in sorted(os.listdir(path)):
            traverse(h, os.path.join(path, entry))
    elif stat.S_ISREG(rs.st_mode):
        h.update('reg ' + quoted_name + ' ')
        h.update(str(rs.st_size) + ' ')
        h.update(file_hash(path) + '\n')
    else: pass # silently symlinks and other special files
h = hashlib.sha256()
for root in sys.argv[1:]: traverse(h, root)
h.update('end\n')
print h.hexdigest()
0'; # separator
  find -type f -exec sha256sum {} + | sort -z; # file hashes
  echo | tr '\n' 'q4312079q0'; # separator
  echo "End of hashed data."; # End of input marker
} | sha256sum
 


评论


好的,这有效,谢谢。但是有没有不包含任何元数据的方法吗?现在我只需要实际内容。

–user17429
2012年4月6日,1:12

LC_ALL = C如何从不同环境中进行检查...(+ 1 btw)

– Peter.O
2012年4月6日在6:16



您为此编写了一个完整的Python程序?谢谢!这确实超出了我的预期。 :-)无论如何,我将检查这些方法以及Warren的新选项1。

–user17429
2012年4月6日17:33

好答案。如果要在多台计算机和OS上运行,则必须使用LC_ALL = C设置排序顺序。

–达沃·库伯拉尼克(Davor Cubranic)
16年8月3日在20:52



cpio -o-是什么意思? cpio默认不使用stdin / out吗? GNU cpio 2.12产生cpio:参数过多

– Jan Tojnar
16年8月12日在12:40

#3 楼

如果您的目标只是查找两个目录之间的差异,请考虑使用diff。

尝试以下操作:

diff -qr dir1 dir2


评论


是的,这也很有用。我认为您在该命令中指的是dir1 dir2。

–user17429
2012年4月6日17:35

当可以避免使用GUI时,我通常不使用GUI,但是对于目录差异而言,kdiff3很棒,并且可以在许多平台上使用。

– sinelaw
2012年4月17日在2:21

该命令也会报告不同的文件。

– Serge Stroobandt
2014年4月2日在15:02

#4 楼

看看md5deep。 md5deep的一些您可能会感兴趣的功能:

递归操作-md5deep能够递归检查整个目录树。也就是说,为目录中的每个文件以及每个子目录中的每个文件计算MD5。
比较模式-md5deep可以接受一系列已知哈希并将它们与一组输入文件进行比较。程序可以显示与已知哈希列表匹配的输入文件,也可以显示不匹配的输入文件。
...


评论


很好,但是无法正常工作,它说... / foo:是目录,这有什么用?

–卡米洛·马丁(Camilo Martin)
2014年10月2日,下午1:21

单独使用md5deep并不能解决OP的问题,因为它不打印合并的md5sum,它仅打印目录中每个文件的md5sum。也就是说,您可以md5sum md5deep的输出-不完全是OP想要的,但是很接近!例如对于当前目录:md5deep -r -l -j0。 | md5sum(其中-r是递归的,-l表示“使用相对路径”,以便在尝试比较两个目录的内容时文件的绝对路径不会受到干扰,并且-j0表示使用1个线程来防止不确定性由于个别的md5sum以不同的顺序返回)。

– Steve
2015年10月14日在12:34

如何忽略路径中的某些文件/目录?

–山迪潘·纳斯(Sandeepan Nath)
16-10-21在13:17

我喜欢最喜欢的答案,但这是更简单的imo。谢谢!

–FilipDupanović
20-2-14在22:43

#5 楼

解决方案:

$ pip install checksumdir
$ checksumdir -a md5 assets/js
981ac0bc890de594a9f2f40e00f13872
$ checksumdir -a sha1 assets/js
88cd20f115e31a1e1ae381f7291d0c8cd3b92fad


可以快速,轻松地解决方案,然后进行bash脚本编写。 /checksumdir/1.0.5

评论


如果没有pip,则可能需要使用yum -y install python-pip(或dnf / apt-get)进行安装

–德米特里·谢梅诺夫(DmitrySemenov)
16 Mar 8 '16 at 2:55

#6 楼

您可以递归哈希每个文件,然后哈希结果文本:

> md5deep -r -l . | sort | md5sum
d43417958e47758c6405b5098f151074 *-


md5deep是必需的。

评论


而不是md5deep,请在ubuntu 16.04上使用hashdeep,因为md5deep软件包只是hashdeep的过渡虚拟对象。

–palik
17年11月8日在15:22

我尝试了hashdeep。它不仅输出散列,还输出一些标头,包括从以下位置调用的##:/ home / myuser / dev /,这是当前路径;以及## $ hashdeep -s -r -l〜/ folder /。这必须进行排序,因此如果您更改当前文件夹或命令行,则最终哈希将有所不同。

–卡车
18年8月23日在8:28

#7 楼

仅文件内容,不包括文件名
我需要一个仅检查文件名的版本,因为内容位于不同的目录中。
这个版本(沃伦·扬的答案)有很大帮助,但是我的md5sum版本输出文件名(相对于我运行命令的路径),并且文件夹名称不同,因此,即使单个文件的校验和匹配,最终的校验和也没有。
要解决此问题,我只需要从find输出的每一行中剥离文件名(使用cut仅选择第一个单词,用空格隔开):
find -s somedir -type f -exec md5sum {} \; | cut -d" " -f1 | md5sum


评论


您可能还需要对校验和进行排序,以获得可重复的列表。

–eckes
16-3-22在21:34

#8 楼

来自Nix软件包管理器的nix-hash


命令nix-hash计算每个路径内容的加密哈希值并将其打印在标准输出上。默认情况下,它会计算MD5哈希,但也可以使用其他哈希算法。哈希以十六进制形式打印。

哈希是通过每个路径的序列化来计算的:以路径为根的文件系统树的转储。这允许对目录
和符号链接进行哈希处理
以及常规文件。转储采用nix-store --dump生成的NAR格式。因此,nix-hash路径与nix-store
--dump path |产生相同的
加密哈希。 md5sum。


#9 楼

作为此出色答案的后续措施,如果您发现自己想加快大目录的校验和的计算,请尝试使用GNU Parallel:
这是使用带有md5的Mac,请根据需要进行替换。)

-k标志很重要,它指示parallel保持顺序,否则即使文件是相同。 -n 100表示要使用100个参数运行md5的每个实例,这是您可以调整的参数以获得最佳运行时间。另请参阅-Xparallel标志(尽管在我的情况下会导致错误。)

#10 楼

我将此片段用于中等音量:

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 cat | md5sum -

XXXL:

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 tail -qc100 | md5sum -

评论


-xdev标志有什么作用?

–czerasz
17年5月4日在6:35

它要求您键入:手动查找并阅读该精美手册;)

– poige
17年5月4日在12:43



好点子 :-)。 -xdev不要降级其他文件系统上的目录。

–czerasz
17年5月4日在16:31

请注意,这将忽略新的空文件(例如,如果您触摸文件)。

–罗恩·约翰(RonJohn)
18年5月12日在23:08

在许多情况下,这将产生具有完全不同的文件和目录结构的相同md5sum。如果重命名文件和目录不会改变文件的排序顺序,则根本不会改变。所以我不推荐这种方法。

–汉斯·彼得·斯托尔
19年7月2日在19:20

#11 楼

一个好的树校验和就是Git的tree-id。不幸的是,没有可用的独立工具可以做到这一点(至少我不知道),但是如果您有Git方便的话您可以假装建立一个新的存储库,然后将要检查的文件添加到索引中。

这允许您生成(可重现的)树形哈希-仅包含内容,文件名和一些简化的文件模式(可执行)。

#12 楼

这个脚本经过了严格的测试,并支持许多操作,包括查找重复项,对数据和元数据进行比较,显示添加以及更改和删除,您可能会喜欢Fingerprint。不会为一个目录生成单个校验和,而是一个转录文件,其中包含该目录中所有文件的校验和。

包括校验和,文件名和文件大小。默认情况下,它同时使用index.fingerprintMD5。现在,您需要保留该文件以进行验证。

#13 楼

我既不想要新的可执行文件也不想要笨拙的解决方案,所以这是我的看法:

#!/bin/sh
# md5dir.sh by Camilo Martin, 2014-10-01.
# Give this a parameter and it will calculate an md5 of the directory's contents.
# It only takes into account file contents and paths relative to the directory's root.
# This means that two dirs with different names and locations can hash equally.

if [[ ! -d "" ]]; then
    echo "Usage: md5dir.sh <dir_name>"
    exit
fi

d="$(tr '\' / <<< "" | tr -s / | sed 's-/$--')"
c=$((${#d} + 35))
find "$d" -type f -exec md5sum {} \; | cut -c 1-33,$c- | sort | md5sum | cut -c 1-32


#14 楼

迁移到POSIX存档格式会影响基于GNU Tar的校验和

此答案旨在作为对使用Tar输出对目录内容进行哈希处理的方法的补充更新(除其他事项外)从那以后,沃伦·杨(Warren Young)和吉勒斯(Gilles)给出了出色的答案。 (略)高级的“ POSIX 1003.1-2001(pax)格式”。他们还在上游(在GNU Tar的开发人员中)讨论执行相同的迁移,例如,请参见GNU Tar手册本页最后的段落:


GNU的默认格式tar是在编译时定义的。您可以通过运行tar --help并检查其输出的最后几行来对其进行检查。通常,将GNU tar配置为以gnu格式创建档案,但是,将来的版本将切换为posix。使用GNU Tar。)

在本例中,我们将目录内容tar并散列结果,并且不采取特定措施,将GNU格式更改为POSIX格式将产生以下结果:


尽管目录内容相同,但校验和的结果将是不同的。 。

后者来自于以下事实,即POSIX(pax)格式包括扩展的pax标头,这些标头由默认格式为GNU Tar中的%d/PaxHeaders.%p/%f的格式字符串确定。在该字符串中,说明符%p被生成的Tar进程的进程ID替换,当然,这在运行之间是不同的。有关详细信息,请参见GNU Tar手册的这一节,尤其是这一节。

刚刚从2019年3月28日开始,上游接受了一个提交,可以缓解此问题。
以下替代选项:


使用Tar选项--format=gnu明确告诉Tar以“旧”格式生成档案。这是验证“旧”校验和所必需的。
使用较新的POSIX格式,但显式指定合适的pax标头,例如--pax-option="exthdr.name=%d/PaxHeaders/%f"。但是,这破坏了与“旧”校验和的向后兼容性。

这是我经常使用的Bash代码片段,用于计算目录内容的校验和,包括元数据: >
( export LC_ALL=C
  find <paths> ! -type s -print0 |
  sort -z |
  tar cp --format=gnu --numeric-owner \
         --atime-preserve \
         --no-recursion --null --files-from - |
  md5sum --binary; )


在这里,<paths>被用空格分隔的校验和要覆盖的所有目录的路径列表代替。在其他答案中已经充分讨论了使用C语言环境,文件名的空字节分隔以及使用查找和排序来获取档案中文件的文件系统独立顺序的目的。



此外,我将表达式LC_ALL! -type s一起使用,以避免如果套接字文件是目录内容的一部分时Tar发出警告:GNU Tar不存档套接字。如果您希望收到有关套接字跳过的通知,请不要使用该表达式。 。

如果任何find位于只读安装的设备上,则最好省略Tar的--numeric-owner选项。否则,将警告您访问时间戳记Tar无法还原的每个文件。对于启用写功能的--atime-preserve,我可以使用此选项将访问时间戳保留在哈希目录中。

Tar选项<paths>已在Gilles提案中使用,它可以防止Tar自己递归地下降到目录中,而是对从排序的<paths>输出中馈送的内容进行逐个文件操作。最后,我使用--no-recursion是不正确的:我实际上使用find

#15 楼

强大而干净的方法


首先,不要浪费可用内存!散列文件而不是整个文件。
针对不同需求/目的的不同方法(以下全部内容或选择适用的方法):


仅散列目录树中所有条目的条目名称
散列所有条目的文件内容(保留元数据,如inode编号,ctime,atime,mtime,size等,您便会知道)
对于符号链接,其内容为引用名称。对其进行哈希处理或选择跳过
对哈希表项的内容进行哈希处理时是否跟随符号链接(已解析名称)
如果是目录,则其内容仅是目录项。在递归遍历时,它们最终将被散列,但是是否应该对该级别的目录条目名称进行散列以标记该目录?在需要散列以快速识别更改而无需深入遍历以散列内容的用例中很有用。一个例子是文件的名称更改,但其余内容保持不变,并且都是相当大的文件
妥善处理大文件(同样要注意RAM)
处理非常深的目录树(注意打开的文件描述符)
处理非标准文件名
如何继续处理套接字,管道/ FIFO,块设备,char设备?还必须对它们进行哈希处理吗?
在遍历时不要更新任何条目的访问时间,因为这在某些用例中会产生副作用并且会产生反作用(直观)。

这就是我的头等大事,任何花了一些时间从事这一工作的人实际上都会抓到其他陷阱和死角。

这是一个工具(免责声明:我是它的贡献者)dtreetrawl,内存非常轻巧,可以解决大多数情况,可能有些麻烦,但很有帮助。


Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Hash the files to produce checksums(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file



人类友好输出示例:


...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0



评论


总是欢迎提供一般性建议,但是最好的答案是特定的,并在适当的地方提供代码。如果您有使用该工具的经验,请把它包括在内。

–bu5hman
18年1月7日在11:54

@ bu5hman当然!自从我参与了它的开发工作以来,我还不太满意地说(高兴吗?)更多关于它的运作情况。

–六千
18年1月7日在13:56

#16 楼

单独处理每个目录中的所有文件。

# Calculating
find dir1 | xargs md5sum > dir1.md5
find dir2 | xargs md5sum > dir2.md5
# Comparing (and showing the difference)
paste <(sort -k2 dir1.md5) <(sort -k2 dir2.md5) | awk ' != '


#17 楼

如果您不需要md5,可以尝试

find . -type f | xargs cksum | cksum


评论


问题专门要求md5

– RalfFriedl
19年4月5日在5:09

#18 楼

我使用以下方法来确定目录的内容/属性是否已更改:

cd /path/to/dir; ls -lnAR --time-style=+%s . | md5sum


如果您还想跟踪扩展属性中的更改:

cd /path/to/dir; (ls -lnAR --time-style=+%s .; getfacl -Rns .) | md5sum


在正常情况下,由于文件修改时间已经表明文件内容已发生更改,因此无需检查文件内容。

注意:


cd / path / to / dir-使校验和抗目录重定位
-n -使校验和在具有不同uid / gid映射的系统之间持久化
-A-包括除虚线以外的所有文件(包括-a)。和..
--time-style = +%s-如果没有它,则校验和完成后1分钟内所做的更改可能无法跟踪,此输出在rsync副本之间也是持久的(与--full-time选项不同)

如果仍然要检查文件内容:tar c -C /path/to/dir | md5sum或具有扩展属性:cd /path/to/dir; (tar c .; getfacl -Rns .) | md5sum

更新:

以使其工作在更广泛的系统上,我不得不设置区域设置,还必须使用awk从ls输出中过滤出硬链接计数和目录大小:

cd /path;LC_ALL=C ls -lnAR --time-style=+%s .|awk '{=0;~/^d/&&=0;print}'|md5sum


#19 楼

单行代码:

find directory -exec md5sum {} \; 2>&1 | sort -k 2 | md5sum


此列表列出了所有文件和目录,并为每个文件和目录获取md5sum。然后获取所有内容的md5sum。我们只是将此消息移至标准输出。

#20 楼

到目前为止,最快的方法仍然是使用tar。借助其他一些参数,我们还可以消除元数据造成的差异。 >
tar -C <root-dir> -cf - --sort=name <dir> | sha256sum

忽略时间
如果您不关心访问时间或修改时间,也可以使用--mtime='UTC 2019-01-01' 之类的东西来确保所有时间戳都相同。
忽略所有权
通常,我们需要添加--group=0 --owner=0 --numeric-owner来统一所有者元数据。
忽略一些文件
使用--exclude=PATTERN

#21 楼

如果您安装了带有pip的Python 3,则可以使用我的pyfstools软件包。快速使用:
$ pip install git+https://github.com/sorgloomer/pyfstools.git@main
...
$ python -m pyfstools hash --algo md5 .
dir 88c17b149c1d9fef50f642b698cef9e6