我如何计算一个目录的MD5校验和?

我需要为一个特定types(例如*.py )的所有文件计算一个摘要md5校验和,并放在一个目录和所有子目录下。

什么是最好的方法来做到这一点?

编辑:build议的解决scheme是非常好的,但这不完全是我所需要的。 我正在寻找一个解决scheme来获得一个统一的校验和,将唯一标识目录作为一个整体 – 包括其所有子目录的内容。

 find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum 

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

我已经通过复制一个testing目录来testing:

 rsync -a ~/pybin/ ~/pybin2/ 

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

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

 2bcf49a4d19ef9abd284311108d626f1 - 

立即创build一个tar归档文件并将其传递给md5sum

 tar c dir | md5sum 

这会产生一个应该是唯一的文件和子目录设置的md5sum。 磁盘上没有创build文件。

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

  • tar按照存储在文件系统中的顺序处理目录条目,并且无法更改此顺序。 如果你在不同的地方有“相同的”目录,这个有效的结果可能会产生完全不同的结果,而且我也不知道如何解决这个问题(tar不能按照特定的顺序“sorting”它的input文件)。
  • 我通常关心的是groupid和ownerid数字是否相同,不一定是组/所有者的string表示是否相同。 这与rsync -a --delete是一致的:它实际上同步所有的东西(减去xattrs和acls),但它会根据它的ID同步所有者和组,而不是根据string表示。 因此,如果您同步到不一定具有相同用户/组的不同系统,则应将--numeric-owner标志添加到tar
  • tar会包含你正在检查的目录的文件名,只是要注意的东西。

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

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

最后,大多数build议的解决scheme不能一致sorting,因为整个系统的sorting可能不同。

这是我提出的解决scheme:

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

有关此解决scheme的说明

  • LC_ALL=C是为了确保跨系统的可靠sorting顺序
  • 这并没有区分目录“named \ nwithanewline”和“named”和“withanewline”两个目录,但是发生这种可能性似乎不太可能。 一个人通常会用-print0标志来修复这个问题,但是由于这里还有其他的东西,所以我只能看到一些解决scheme,这会让命令变得更加复杂,所以值得。

PS:我的一个系统使用一个有限的busybox find ,它不支持-exec-print0标志,还附加了“/”来表示目录,而findutils找不到,所以对于这台机器我需要运行:

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

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

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

 find /path -type f | sort -u | xargs cat | md5sum 

为了完整起见,有md5deep(1) ; 由于* .pyfilter的要求,它不是直接适用的,但是应该和find(1)一起使用。

看看这个和这个更详细的解释。

一个最适合我的解决scheme:

 find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum 

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

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

与其他答案的问题:

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

tar c - "$path" | md5sum

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

 find /path -type f | sort -u | xargs cat | md5sum 

如果你想要一个跨越整个目录的md5sum,我会做类似的事情

 cat *.py | md5sum 

检查所有文件,包括内容和文件名

 grep -ar -e . /your/dir | md5sum | cut -c-32 

同上,但只包含* .py文件

 grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32 

如果你愿意,你也可以关注符号链接

 grep -aR -e . /your/dir | md5sum | cut -c-32 

其他选项,你可以考虑使用grep

 -s, --no-messages suppress error messages -D, --devices=ACTION how to handle devices, FIFOs and sockets; -Z, --null print 0 byte after FILE name -U, --binary do not strip CR characters at EOL (MSDOS/Windows) 

GNU发现

 find /path -type f -name "*.py" -exec md5sum "{}" +; 

技术上你只需要运行ls -lR *.py | md5sum ls -lR *.py | md5sum 。 除非你担心有人修改这些文件并将它们恢复到原来的date,并且从不改变文件的大小,否则ls的输出应该告诉你文件是否已经改变。 我的unix-foo很弱,所以你可能需要更多的命令行参数来获得创build时间和修改时间来打印。 ls也会告诉你,如果对文件的权限已经改变了(如果你不关心的话,我确定有开关可以closures它)。

我使用HashCopy来做到这一点。 它可以在单个文件或目录上生成并validationMD5和SHA。 它可以从www.jdxsoftware.org下载。

使用md5deep

md5deep -r FOLDER | awk '{print $1}' | sort | md5sum

我有同样的问题,所以我想出了这个脚本,只列出目录中的文件的md5sum,如果它find一个子目录再次从那里运行,为此发生脚本必须能够通过当前目录或从一个子目录,如果所述parameter passing$ 1

 #!/bin/bash if [ -z "$1" ] ; then # loop in current dir ls | while read line; do ecriv=`pwd`"/"$line if [ -f $ecriv ] ; then md5sum "$ecriv" elif [ -d $ecriv ] ; then sh myScript "$line" # call this script again fi done else # if a directory is specified in argument $1 ls "$1" | while read line; do ecriv=`pwd`"/$1/"$line if [ -f $ecriv ] ; then md5sum "$ecriv" elif [ -d $ecriv ] ; then sh myScript "$line" fi done fi 

如果你真的想独立于文件系统属性和某些tar版本的位级差异,你可以使用cpio:

 cpio -i -e theDirname | md5sum 

还有两个解决scheme:

创build:

 du -csxb /path | md5sum > file ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file 

检查:

 du -csxb /path | md5sum -c file ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file