如何计算目录的md5校验和?

vic*_*orz 129 linux directory md5sum

我需要为*.py位于目录和所有子目录下的特定类型(例如)的所有文件计算摘要md5校验和.

最好的方法是什么?

编辑:建议的解决方案非常好,但这不是我需要的.我正在寻找一种解决方案,以获得单个摘要校验和,它将唯一地标识整个目录 - 包括其所有子目录的内容.

ire*_*ses 161

动态创建tar归档文件并将其传递给md5sum:

tar c dir | md5sum
Run Code Online (Sandbox Code Playgroud)

这会生成一个md5sum,它对于您的文件和子目录设置应该是唯一的.磁盘上没有创建文件.

  • @CharlesB只有一个校验和,你永远不知道哪个文件是不同的.问题是关于目录的单一校验和. (25认同)
  • `ls -alR dir | md5sum`.这甚至更好,没有压缩只是读取.它是唯一的,因为内容包含文件的mod时间和大小;) (14认同)
  • @ Daps0l - 我的命令中没有压缩.你需要为gzip添加`z`,或为bzip2添加`j`.我没做过. (13认同)
  • 注意这样做会在校验和计算中集成文件和其他东西的时间戳,而不仅仅是文件的内容 (7认同)
  • 这很可爱,但它确实不起作用.无法保证两次或两台不同计算机上的"同一组文件"会产生相同的结果. (7认同)
  • 问题是你要比较的另一个目录可能在另一台带有另一个文件系统的机器上,并且tar无法保证它如何捆绑文件的顺序.因此,您可以使所有文件单独具有正确的校验和,但tar | md5计算将有所不同. (4认同)
  • 除非它不同,你不知道哪个目录或文件是罪魁祸首...... (3认同)
  • 它对我来说不起作用,我认为主要是因为我将文件复制到外部硬盘驱动器,所以它们的元数据更改了,tar也包装了它.也许tar有一些跳过元数据的选项. (3认同)

unu*_*tbu 147

find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
Run Code Online (Sandbox Code Playgroud)

find命令列出以.py结尾的所有文件.为每个.py文件计算md5sum.awk用于挑选md5sums(忽略文件名,这可能不是唯一的).md5sums已排序.然后返回此排序列表的md5sum.

我通过复制测试目录测试了这个:

rsync -a ~/pybin/ ~/pybin2/
Run Code Online (Sandbox Code Playgroud)

我重命名了〜/ pybin2中的一些文件.

find...md5sum命令为两个目录返回相同的输出.

2bcf49a4d19ef9abd284311108d626f1  -
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果重命名文件,将生成相同的校验和.因此,如果您将文件布局视为签名的一部分,那么这并不真正适合"将唯一标识整个目录的校验和". (20认同)
  • @ zim2001:是的,它可能被改变了,但是当我理解这个问题时(特别是由于OP在问题下的评论),OP希望任何两个目录被认为是相同的,如果文件的*内容*是相同的,无论文件名甚至相对路径. (4认同)

Die*_*_be 44

ire_and_curses的使用建议tar c <dir>有一些问题:

  • tar以文件系统中存储的顺序处理目录条目,并且无法更改此顺序.如果你在不同的地方有"相同"的目录,这实际上可以产生完全不同的结果,我知道无法解决这个问题(tar不能按特定顺序"排序"其输入文件).
  • 我通常关心groupid和ownerid数字是否相同,不一定是组/所有者的字符串表示是否相同.这与例如一致rsync -a --delete:它几乎同步所有内容(减去xattrs和acls),但它将根据其ID同步所有者和组,而不是字符串表示.因此,如果您同步到不一定具有相同用户/组的其他系统,则应将该--numeric-owner标志添加到tar
  • tar将包含您正在检查的目录的文件名,只需注意一些事项.

只要没有解决第一个问题(或除非你确定它不会影响你),我就不会使用这种方法.

find上面提出的基础解决方案也不好,因为它们只包含文件,而不是目录,如果校验和应该记住空目录,这就成了一个问题.

最后,大多数建议的解决方案不能一致地排序,因为整个系统的整理可能不同.

这是我提出的解决方案:

dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Run Code Online (Sandbox Code Playgroud)

关于此解决方案的说明

  • LC_ALL=C是为了确保跨系统的可靠排序顺序
  • 这不区分目录"named \nwithanewline"和两个目录"named"和"withanewline",但这种情况发生的可能性似乎非常小.人们通常用一个-print0标志来解决这个问题,find但是由于这里还有其他的东西,我只能看到解决方案会让命令变得更加复杂然后它的价值.

PS:我的一个系统使用有限的busybox find,它不支持-exec也不支持-print0标志,并且它附加'/'来表示目录,而findutils find似乎没有,所以对于这台机器我需要运行:

dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum
Run Code Online (Sandbox Code Playgroud)

幸运的是,我的名字中没有带换行符的文件/目录,所以这不是该系统的问题.

  • 都.它只取决于每个目录中的目录条目的顺序.AFAIK目录条目(在文件系统中)只是按照"在目录中创建文件"的顺序创建.一个简单的例子:$ mkdir a; 触摸a/file-1; 触摸a/file-2 $ mkdir b; 触摸b/file-2; touch b/file-1 $(cd a; tar -c.| md5sum)fb29e7af140aeea5a2647974f7cdec77 - $(cd b; tar -c.| md5sum)a3a39358158a87059b9f111ccffa1023 - (2认同)

小智 13

如果你只关心文件而不是空目录,这很好用:

find /path -type f | sort -u | xargs cat | md5sum
Run Code Online (Sandbox Code Playgroud)

  • 如果您不“cat”文件,“md5sum”的输入将是“find”的输出,“find”是文件名(和路径)的列表,**不是**这些文件的内容。 (2认同)

Mic*_*rin 10

为了完整起见,有md5deep(1) ; 由于*.py过滤器要求,它不能直接应用,但应与find(1)一起使用.


Tia*_*opo 9

一个最适合我的解决方案:

find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum
Run Code Online (Sandbox Code Playgroud)

它为什么最适合我的原因:

  1. 处理包含空格的文件名
  2. 忽略文件系统元数据
  3. 检测文件是否已重命名

其他答案的问题:

文件系统元数据不会被忽略:

tar c - "$path" | md5sum

不处理包含空格的文件名,也不检测文件是否已重命名:

find /path -type f | sort -u | xargs cat | md5sum
Run Code Online (Sandbox Code Playgroud)