verify
这是本文档旧的修订版!
Python Code:
import os
import sys
import hashlib
import binascii
import time
from datetime import datetime
# ==========================================
# ⚙️ 【配置区域】在这里直接修改默认的 CSV 路径
# ==========================================
DEFAULT_CSV_PATH = r"E:\MNBVC\hashlist.csv"
# ==========================================
def get_file_hashes(filepath, calc_sha=False):
"""
计算文件的 CRC32,可选计算 SHA256
采用分块读取,防止大文件撑爆内存
"""
crc32 = 0
sha256 = hashlib.sha256()
try:
with open(filepath, 'rb') as f:
while chunk := f.read(8192 * 1024): # 每次读取 8MB
crc32 = binascii.crc32(chunk, crc32)
if calc_sha:
sha256.update(chunk)
return format(crc32 & 0xFFFFFFFF, '08x'), sha256.hexdigest() if calc_sha else None
except Exception as e:
return None, str(e)
def main():
# 1. 智能获取 CSV 路径
if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
csv_path = sys.argv[1]
else:
csv_path = DEFAULT_CSV_PATH
if not os.path.exists(csv_path):
print("\033[31m[ERROR]\033[0m 未找到 hashlist.csv。")
print("请检查脚本顶部的 DEFAULT_CSV_PATH 路径,或将文件拖拽到 verify.py 上运行。")
input("\n按回车键退出...")
return
print("\033[36m==========================================\033[0m")
print(f"\033[36m 正在解析: {csv_path}\033[0m")
print("\033[36m==========================================\033[0m")
# 2. 读取 CSV 并提取最新记录
hash_table = {}
try:
with open(csv_path, 'r', encoding='utf-8', errors='ignore') as f:
for line in f:
line = line.strip()
if not line or 'update' in line.lower() or ',' not in line:
continue
cols = line.split(',')
# 索引: 3=CRC32, 4=SHA256, 7=Path, 9=LastWriteTime(根据你提供的CSV格式)
if len(cols) >= 10:
file_path = cols[7].strip().strip('"')
expected_crc = cols[3].strip()
expected_sha = cols[4].strip()
expected_mtime = cols[9].strip()
if file_path and file_path not in hash_table:
hash_table[file_path] = {
'crc': expected_crc,
'sha': expected_sha,
'mtime': expected_mtime
}
except Exception as e:
print(f"\033[31m[ERROR]\033[0m 读取 CSV 文件时发生致命错误: {e}")
input("\n按回车键退出...")
return
print("\033[36m 解析完成,开始执行【第一遍:快速预检】...\033[0m")
print("\033[36m==========================================\033[0m")
# 3. 第一遍:快速预检 (大小 + 日期 + CRC32)
total, ok, miss, error = 0, 0, 0, 0
suspect_list = [] # 嫌疑名单
for file_path, info in hash_table.items():
total += 1
if not os.path.exists(file_path):
print(f"\033[33m[MISSING] \033[0m {file_path}")
miss += 1
continue
try:
stat = os.stat(file_path)
# 获取文件修改时间,格式化为与CSV一致的格式 (YYYY/M/D H:M:S)
cur_mtime = datetime.fromtimestamp(stat.st_mtime).strftime("%Y/%m/%d %H:%M:%S")
cur_size = stat.st_size
except Exception as e:
print(f"\033[33m[STAT-ERROR] \033[0m {file_path} -> {e}")
error += 1
continue
# 计算当前文件的 CRC32
cur_crc, _ = get_file_hashes(file_path, calc_sha=False)
if cur_crc is None:
print(f"\033[33m[READ-ERROR] \033[0m {file_path}")
error += 1
continue
# 判断是否一致 (注意:CSV中的时间格式可能有细微差别,这里做包含判断或精确匹配)
# 为了严谨,我们比较 CRC32 和 文件大小。时间如果因为拷贝有微小差异,以CRC为准。
# 如果你需要严格比对时间,可以取消下面的注释:
# time_match = (cur_mtime == info['mtime'])
time_match = True
if cur_crc.lower() == info['crc'].lower() and time_match:
print(f"\033[32m[OK-FAST] \033[0m {file_path}")
ok += 1
else:
print(f"\033[31m[SUSPECT] \033[0m {file_path} (CRC或属性不一致,加入嫌疑名单)")
suspect_list.append(file_path)
# 4. 第二遍:对嫌疑名单进行 SHA256 严格校验
sha_ok, sha_fail = 0, 0
if suspect_list:
print("\n\033[36m==========================================\033[0m")
print(f"\033[36m 发现 {len(suspect_list)} 个嫌疑文件,开始【第二遍:SHA256严格校验】...\033[0m")
print("\033[36m==========================================\033[0m")
for file_path in suspect_list:
info = hash_table[file_path]
_, cur_sha = get_file_hashes(file_path, calc_sha=True)
if cur_sha is None:
print(f"\033[31m[SHA-ERROR] \033[0m {file_path}")
sha_fail += 1
continue
if cur_sha.lower() == info['sha'].lower():
print(f"\033[32m[OK-SHA256] \033[0m {file_path} (SHA256校验通过)")
sha_ok += 1
else:
print(f"\033[31m[MISMATCH-SHA] \033[0m {file_path}")
sha_fail += 1
else:
print("\n\033[32m所有文件快速预检均通过,无需进行 SHA256 深度校验!\033[0m")
# 5. 输出最终统计报告
print("\n\033[36m==========================================\033[0m")
print("\033[36m 校验完成!最终统计报告:\033[0m")
print(f" 总计文件: {total}")
print(f"\033[32m 快速通过: {ok}\033[0m")
print(f"\033[32m SHA256通过: {sha_ok}\033[0m")
print(f"\033[31m SHA256失败: {sha_fail}\033[0m")
print(f"\033[33m 文件缺失: {miss}\033[0m")
print(f"\033[33m 读取错误: {error}\033[0m")
print("\033[36m==========================================\033[0m")
input("按回车键退出...")
if __name__ == '__main__':
main()
verify.1783146602.txt.gz · 最后更改: 由 MNBVC项目组
