我如何计算一个目录的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
为什么最适合我的原因是:
- 处理包含空格的文件名
- 忽略文件系统元数据
- 检测文件是否已被重命名
与其他答案的问题:
文件系统元数据不会被忽略:
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