☰
一文详解md5sum:在Ubuntu和macOS上构建跨平台文件完整性校验工具
2026/10/27 1:30:03 网站建设 项目流程

在数字时代,文件传输和存储过程中可能会遭遇各种意外情况:网络传输错误、存储介质损坏、恶意篡改等。这些风险可能导致关键文件损坏或内容被修改,进而引发严重后果。文件完整性校验技术应运而生,成为确保数据安全的必要手段。

MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希算法,能够为任意长度的数据生成唯一的128位哈希值。虽然MD5在密码学领域已不再安全,但在文件完整性校验方面,它仍然是一个简单有效的工具。

本文将介绍 Linux(Ubuntu)下的md5sum命令,以及 macOS 上对应的md5命令,并给出一个在 Ubuntu 和 macOS 上都可直接运行的自动化文件完整性校验脚本。

一、md5sum 与 md5 工具

md5sum是 GNU coreutils 中的一个经典命令行工具,其核心功能是计算并验证文件的 MD5 哈希值。MD5 哈希如同一份文件的“数字指纹”,任何微小的内容改动都会导致其哈希值发生剧烈变化。通过比较文件当前生成的MD5值与之前记录的原始值,md5sum能够高效、准确地判断文件在传输、存储或备份过程中是否保持了完整性,即是否未被意外损坏或恶意篡改。

macOS 同样属于 Unix 类系统,但并没有自带md5sum,而是提供了 BSD 版本的md5命令。两者针对同一个文件计算出的 MD5 值完全相同,差异主要在于命令参数和输出格式:

  • md5sum file输出哈希值 文件名,并支持用-c直接校验;
  • md5 file默认输出MD5 (file) = 哈希值,需要加-r才能得到与 md5sum 一致的哈希值 文件名格式,并且不支持-c校验模式。

两个平台的常用命令对比如下:

操作Ubuntu(md5sum)macOS(md5)
计算单个文件的哈希md5sum filemd5 -r file
仅输出哈希值md5sum file | awk '{print $1}'md5 -q file
批量生成find ... -exec md5sum {} \;find ... -exec md5 -r {} \;
批量校验md5sum -c checksums.md5逐行比对(见下文),或使用gmd5sum -c checksums.md5

如果希望在 macOS 上直接使用md5sum的完整功能,可以安装 GNU coreutils:brew install coreutils。安装后会提供带g前缀的gmd5sum,其用法与md5sum完全一致。

1. 生成单个文件的MD5校验值

若您希望在终端中直接查看某个文件的MD5哈希值,可以使用以下命令,它将输出一个128位的哈希值与对应的文件名:

# Ubuntu:生成文件的MD5值并显示在终端md5sum filename.txt

在 macOS 上对应的写法为:

# macOS:-r 参数输出 "哈希值 文件名" 格式md5-rfilename.txt# 如果只需要哈希值本身md5-qfilename.txt

如果您需要将生成的MD5校验值保存下来以供后续使用,可以将输出重定向至一个文件,这样会创建一个便于日后校验的MD5记录文件:

# Ubuntu:将MD5值保存到文件md5sum filename.txt>checksum.md5# macOS:将MD5值保存到文件md5-rfilename.txt>checksum.md5

2. 校验文件完整性

当您拥有一个已存储MD5值的校验文件时,可以使用以下命令批量校验对应文件的完整性,系统会自动比对当前文件的MD5值与记录是否一致:

# Ubuntu:使用保存的MD5文件校验md5sum-cchecksum.md5

macOS 的md5命令没有-c校验模式,需要自行读取校验文件并逐行比对。下面是一个最简实现:

# macOS:逐行读取校验文件并比对whileIFS=read-rline;do[-z"$line"]&&continueexpected="${line%%*}"file="${line#* }"file="${file#}"# 兼容 md5sum 输出中的两个空格if[-f"$file"]&&["$(md5-q"$file")"="$expected"];thenecho"$file: OK"elseecho"$file: FAILED"fidone<checksum.md5

当然,也可以先执行brew install coreutils,然后直接使用gmd5sum -c checksum.md5,获得与 Ubuntu 完全一致的校验体验。

3. 批量处理文件

若要为某个目录下的所有文件生成MD5校验值,可以结合find命令实现批量生成,结果将统一保存到一个汇总文件中:

# Ubuntu:生成目录下所有文件的MD5值find/home/bjxia/demo-typef-execmd5sum{}\;>all_checksums.md5

同样,也可以基于上述生成的汇总文件,对目录中的所有文件进行一次完整的批量校验,确保大量文件的完整性状态一目了然:

# Ubuntu:批量校验md5sum-call_checksums.md5

在 macOS 上,只需把md5sum换成md5 -r:

# macOS:批量生成(输出格式与 md5sum 一致)find~/Downloads/mask-typef-execmd5-r{}\;>all_checksums.md5# macOS:批量校验(使用上一节的循环,或 gmd5sum -c)whileIFS=read-rline;doexpected="${line%%*}"file="${line#* }";file="${file#}"["$(md5-q"$file")"="$expected"]&&echo"$file: OK"||echo"$file: FAILED"done<all_checksums.md5

4. 批量处理时排除指定目录

在实际项目中,我们经常需要排除一些临时或自动生成的目录,例如node_modules或build文件夹,这时可以在find命令中加入排除参数,使生成的MD5记录更加简洁和准确:

# 使用 -not -path 排除目录(GNU find 写法)find/home/bjxia/demo-typef-not-path"*/node_modules/*"-not-path"*/build/*"-execmd5sum{}\;>checksums.md5

需要注意的是,-not、-path这类写法虽然也能被部分 BSD/macOS 版本的find识别,但兼容性并不稳定。更稳妥、也更高效的做法是使用-prune直接跳过整个目录,这种写法在 GNU find 和 BSD find 中均可正常工作:

# Ubuntu:排除 node_modules、build 目录find"$BASE_DIR"\(-namenode_modules-o-namebuild\)-prune-o\-typef-execmd5sum{}\;>checksums.md5# macOS:排除 node_modules、build 目录find"$BASE_DIR"\(-namenode_modules-o-namebuild\)-prune-o\-typef-execmd5-r{}\;>checksums.md5

-prune会直接跳过匹配的目录,不再递归遍历其中的内容,因此比“遍历后再用-path过滤”更快。后文的自动化脚本正是采用这种跨平台写法,并借助 Bash 数组组织find参数,避免使用eval,即使路径中包含空格或特殊字符也能安全处理。

二、跨平台自动化脚本

通过编写脚本,我们可以将校验流程自动化,提高工作效率。下面这份自动化校验脚本在 Ubuntu 和 macOS 上均可直接运行:它会自动检测系统可用的 MD5 工具,并处理两个平台在命令参数、输出格式和校验方式上的差异。此外,脚本还支持排除指定目录、通过命令行参数或环境变量配置路径,并自动避免把校验文件自身计算进去。

#!/usr/bin/env bash# check_integrity.sh - 文件 MD5 生成与校验(Linux / macOS 通用)## 用法:# 添加执行权限# chmod +x md5sum.sh# 输入文件:默认当前目录;输出文件:默认 ~/checksums# ./check_integrity.sh# 指定源目录# ./check_integrity.sh ~/Downloads/mask# 指定源目录和输出目录# ./check_integrity.sh ~/Downloads/mask ~/Downloads/mask# 要计算MD5的文件夹(默认当前目录)BASE_DIR="${1:-${BASE_DIR:-$PWD}}"# MD5输出文件夹(默认 ~/checksums)MD5_DIR="${2:-${MD5_DIR:-$HOME/checksums}}"# 要排除的文件夹:用空格分隔多个文件夹名EXCLUDE_DIRS="cmake-build-debug cmake-build-release .idea"if[!-d"$BASE_DIR"];thenecho"错误: 源目录不存在:$BASE_DIR"exit1fi# 转成绝对路径,保证校验文件里记录的是绝对路径BASE_DIR=$(cd"$BASE_DIR"&&pwd)mkdir-p"$MD5_DIR"MD5_DIR=$(cd"$MD5_DIR"&&pwd)# MD5校验文件的完整路径MD5_FILE="$MD5_DIR/md5_checksums.txt"# 检测可用的 MD5 工具:Linux 用 md5sum,macOS 用 md5detect_md5_tool(){ifcommand-vmd5sum>/dev/null2>&1;thenMD5_BIN="md5sum"MD5_STYLE="gnu"elifcommand-vgmd5sum>/dev/null2>&1;thenMD5_BIN="gmd5sum"MD5_STYLE="gnu"elifcommand-vmd5>/dev/null2>&1;thenMD5_BIN="md5"MD5_STYLE="bsd"elseecho"错误: 未找到 md5sum 或 md5 命令"exit1fi}# 构建排除目录的 find 表达式(-prune 写法 BSD/GNU find 都支持)build_find_expr(){FIND_EXPR=()localdirprune=()fordirin$EXCLUDE_DIRS;do[${#prune[@]}-gt0]&&prune+=(-o)prune+=(-name"$dir")doneif[${#prune[@]}-gt0];thenFIND_EXPR+=(\("${prune[@]}"\)-prune-o)fiFIND_EXPR+=(-type f)# 排除校验文件自身,避免输出目录与源目录相同时把自己也计算进去FIND_EXPR+=(!-path"$MD5_FILE")}# 函数:生成MD5generate_md5(){echo"正在生成MD5校验和..."echo"源目录:$BASE_DIR"echo"排除目录:$EXCLUDE_DIRS"# 清空旧文件>"$MD5_FILE"# BSD md5 需要 -r 才能输出 "hash 文件名" 格式if["$MD5_STYLE"="bsd"];thenfind"$BASE_DIR""${FIND_EXPR[@]}"-exec"$MD5_BIN"-r{}\;>"$MD5_FILE"elsefind"$BASE_DIR""${FIND_EXPR[@]}"-exec"$MD5_BIN"{}\;>"$MD5_FILE"fiCOUNT=$(grep-c."$MD5_FILE")echo"已生成$COUNT个文件的MD5校验和"echo"保存到:$MD5_FILE"}# BSD md5 没有 -c 校验模式,这里逐行读取校验文件自行比对verify_md5_bsd(){localline expectedfileactualfailed=0checked=0whileIFS=read-rline||[-n"$line"];do[-z"$line"]&&continue# 兼容 "hash file"(BSD md5 -r)和 "hash file"(GNU md5sum)两种格式expected="${line%%*}"file="${line#* }"while["${file#}"!="$file"];dofile="${file#}"done# GNU md5sum 二进制模式会在文件名前加 *["${file#\*}"!="$file"]&&file="${file#\*}"checked=$((checked+1))if[!-f"$file"];thenprintf'%s: FAILED(文件不存在)\n'"$file"failed=$((failed+1))elseactual=$("$MD5_BIN" -q "$file")if["$actual"="$expected"];thenprintf'%s: OK\n'"$file"elseprintf'%s: FAILED\n'"$file"failed=$((failed+1))fifidone<"$MD5_FILE"if[$failed-gt0];thenprintf'md5: 警告: %s 个文件校验失败(共 %s 个)\n'"$failed""$checked">&2return1fireturn0}# 函数:校验MD5verify_md5(){echo"正在校验文件完整性..."if[!-f"$MD5_FILE"];thenecho"错误: MD5文件不存在,请先生成MD5:$MD5_FILE"return1filocalrc=0if["$MD5_STYLE"="gnu"];then"$MD5_BIN"-c"$MD5_FILE"2>&1||rc=$?elseverify_md5_bsd||rc=$?fiif[$rc-eq0];thenecho""echo"✓ 所有文件完整性校验通过!"return0elseecho""echo"⚠ 文件完整性校验失败!"return1fi}detect_md5_tool build_find_expr# 主菜单echo"文件完整性管理工具"echo"=================="echo"源目录:$BASE_DIR"echo"输出目录:$MD5_DIR"echo"1. 生成MD5校验和"echo"2. 校验文件完整性"echo"3. 重新生成并校验"printf'请选择操作 (1-3): 'read-rchoicecase$choicein1)generate_md5;;2)verify_md5;;3)generate_md5 verify_md5;;*)echo"无效选择"exit1;;esac

2.1 脚本关键实现

  1. 自动检测 MD5 工具:优先使用md5sum(Linux 或安装了 coreutils 的环境),其次尝试gmd5sum,最后回退到 macOS 自带的md5,并用MD5_STYLE区分 GNU 与 BSD 两套处理逻辑。
  2. 生成命令适配:BSD 的md5需要-r参数才能输出与md5sum一致的哈希值 文件名格式,脚本据平台自动添加。
  3. 校验方式适配:GNU 环境直接调用md5sum -c;macOS 环境则逐行读取校验文件,用md5 -q计算后比对,并兼容两种输出格式的空格数量、*标记以及文件丢失的情况。
  4. 跨平台排除目录:用-prune表达式替代-not -path,同时用 Bash 数组拼接参数而不是eval,路径中包含空格时也不会出错。
  5. 路径处理:源目录和输出目录支持“命令行参数 > 环境变量 > 默认值”的优先级,并统一转换为绝对路径,因此切换工作目录后仍能正确校验。
  6. 避免校验文件自校验:当输出目录与源目录相同(例如./md5sum.sh ~/Downloads/mask ~/Downloads/mask)时,脚本会通过! -path "$MD5_FILE"把校验文件自身排除在外,否则每次重新生成都会改变自身内容,导致校验永远失败。
  7. 统计文件数量:使用grep -c而不是wc -l,因为 macOS 的wc在读取标准输入时会输出前导空格。

2.2 使用方法

# 添加执行权限chmod+x md5sum.sh# 默认:校验当前目录,结果保存到 ~/checksums./check_integrity.sh# 指定源目录./check_integrity.sh ~/Downloads/mask# 指定源目录和输出目录(两者可以相同)./check_integrity.sh ~/Downloads/mask ~/Downloads/mask

运行后按提示选择 1(生成)、2(校验)或 3(重新生成并校验)即可。

批量生成MD5校验和:

批量校验MD5校验和:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询