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

时间:2009-11-01 14:00:34

标签: linux directory md5sum

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

最好的方法是什么?

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

17 个答案:

答案 0 :(得分:158)

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

tar c dir | md5sum

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

答案 1 :(得分:144)

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

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

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

rsync -a ~/pybin/ ~/pybin2/

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

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

2bcf49a4d19ef9abd284311108d626f1  -

答案 2 :(得分: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

关于此解决方案的说明:

  • LC_ALL=C是为了确保跨系统的可靠排序顺序
  • 这不区分名为“nwithanewline”的目录和“named”和“withanewline”两个目录,但发生这种情况的可能性似乎非常小。人们通常使用-print0 find标记修复此问题,但由于此处还有其他内容,我只能看到使命令更复杂的解决方案。

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

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

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

答案 3 :(得分:13)

如果您只关心文件而不是空目录,那么这很有效:

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

答案 4 :(得分:10)

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

答案 5 :(得分:9)

最适合我的解决方案:

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

为什么它最适合我:

  1. 处理包含空格的文件名
  2. 忽略文件系统元数据
  3. 检测文件是否已重命名
  4. 其他答案的问题:

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

    tar c - "$path" | md5sum

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

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

答案 6 :(得分:3)

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

的事情
cat *.py | md5sum 

答案 7 :(得分:3)

校验所有文件,包括内容及其文件名

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)

答案 8 :(得分:2)

GNU find

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

答案 9 :(得分:2)

从技术上讲,您只需要运行ls -lR *.py | md5sum。除非您担心有人修改文件并将其触摸回原始日期并且从不更改文件的大小,否则ls的输出应该告诉您文件是否已更改。我的unix-foo很弱,所以你可能需要更多的命令行参数来获得打印的创建时间和修改时间。 ls还会告诉您文件的权限是否已更改(如果您不关心,我确定有开关可以关闭它。)

答案 10 :(得分:2)

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

答案 11 :(得分:2)

使用md5deep

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

答案 12 :(得分:1)

我想补充一点,如果您要对git存储库中的文件/目录执行此操作以跟踪它们是否已更改,那么这是最好的方法:

git log -1 --format=format:%H --full-diff <file_or_dir_name>

如果不是git-directory / repo,那么@ire_and_curses的回答可能是最好的选择:

tar c <dir_name> | md5sum

但是,请注意,tar命令将在其他操作系统和其他东西上运行时更改输出哈希。如果您想避免这种情况,那是最好的方法,即使乍看之下它看起来并不优雅:

find <dir_name> -type f -print0 | sort -z | xargs -0 md5sum | md5sum | awk '{ print $1 }'

答案 13 :(得分:1)

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

cpio -i -e theDirname | md5sum

答案 14 :(得分:1)

我遇到了同样的问题,所以我想出了这个脚本,它只列出了目录中文件的md5sums,如果找到一个子目录,它就会从那里再次运行,为此,脚本必须能够运行通过当前目录或从子目录中,如果所述参数在$ 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

答案 15 :(得分:0)

还有两个解决方案:

创建:

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

答案 16 :(得分:0)

md5sum对我来说很好用,但是我在sort和文件名排序方面遇到问题。所以我改为按md5sum结果排序。我还需要排除一些文件才能创建可比较的结果。

find . -type f -print0 \ | xargs -r0 md5sum \ | grep -v ".env" \ | grep -v "vendor/autoload.php" \ | grep -v "vendor/composer/" \ | sort -d \ | md5sum