思路
整个过程不进行文件处理,如压缩、格式转换,避免哈希值发生变化,所以建议该流程处于末尾。
流程图
代码
哈希记录
import os
import hashlib
import json
import re
def natural_sort_key(s):
"""
用于自然排序的键函数。
自然排序意味着像“1”, “2”, “10”这样的字符串会按照数值的顺序排序,而不是字典顺序。
"""
# 分割字符串,将数字和非数字部分分开,以便于排序
return [int(text) if text.isdigit() else text.lower() for text in re.split('(\d+)', s)]
def calculate_file_hash(file_path, hash_algo='md5'):
"""
计算文件的哈希值,支持多种哈希算法。
:param file_path: 文件的路径
:param hash_algo: 使用的哈希算法,默认为md5
:return: 文件的哈希值字符串,如果计算出错则返回None
"""
hash_func = hashlib.new(hash_algo)
try:
# 以二进制模式打开文件,逐块读取并更新哈希值
with open(file_path, 'rb') as file:
while chunk := file.read(8192):
hash_func.update(chunk)
except Exception as e:
# 如果在读取文件或计算哈希时出错,打印错误信息并返回None
print(f"计算文件哈希时出错: {file_path} - {e}")
return None
# 返回最终的哈希值,作为字符串
return hash_func.hexdigest()
def load_existing_hashes(json_output_path):
"""
从JSON文件中加载现有的哈希值。
:param json_output_path: 存储哈希值的JSON文件路径
:return: 现有哈希值的字典,如果文件不存在或不是有效的JSON格式,则返回空字典
"""
if os.path.exists(json_output_path):
with open(json_output_path, 'r') as json_file:
try:
# 尝试从文件中加载哈希值字典
return json.load(json_file)
except json.JSONDecodeError:
# 如果文件不是有效的JSON格式,返回空字典
return {}
return {}
def calculate_hash(folder_path, json_output_path, merge=False, sort_mode='alphabetical', hash_algo='md5'):
"""
计算指定文件夹中所有文件的哈希值,并将结果保存到JSON文件中。
:param folder_path: 包含待计算哈希值文件的文件夹路径
:param json_output_path: 用于保存哈希值的JSON文件路径
:param merge: 如果为True,则将新的哈希值合并到现有的哈希值字典中,否则创建新的字典
:param sort_mode: 排序模式,可以是'alphabetical'(字典顺序)或'natural'(自然排序)
:param hash_algo: 使用的哈希算法,默认为md5
"""
# 列出文件夹中的所有文件名
filenames = os.listdir(folder_path)
# 根据用户选择进行排序
if sort_mode == 'natural':
filenames.sort(key=natural_sort_key)
elif sort_mode == 'alphabetical':
filenames.sort()
else:
# 如果sort_mode不是已知的合法值,抛出错误
raise ValueError("无效sort_mode,请选择“natural”或“alphabetical”。")
# 加载现有哈希值
file_hashes = load_existing_hashes(json_output_path) if merge else {}
# 遍历文件夹中的每个文件
for filename in filenames:
file_path = os.path.join(folder_path, filename)
if os.path.isfile(file_path):
# 计算文件的哈希值
file_hash = calculate_file_hash(file_path, hash_algo)
if file_hash is not None: # 只有在哈希计算成功时才更新字典
file_hashes[filename] = file_hash
# 将更新后的文件哈希值字典保存到JSON文件中
with open(json_output_path, 'w') as json_file:
json.dump(file_hashes, json_file, indent=4)
print(f"哈希值已保存到:{json_output_path}")
哈希排序
import json
def hash_sorting(a_file, b_file, output_file):
"""
根据JSON文件a中的顺序重新排列JSON文件b中的数据,并将结果保存到输出文件中。
参数:
:param a_file: 包含数据排序顺序的JSON文件路径。
:param b_file: 需要重新排序的JSON文件路径。
:param output_file: 保存重新排序后数据的JSON文件路径。
"""
try:
# 加载a文件中的数据,用于获取数据排序顺序
with open(a_file, 'r') as file:
a_data = json.load(file)
# 加载b文件中的数据,用于建立哈希值到文件名的映射
with open(b_file, 'r') as file:
b_data = json.load(file)
# 建立哈希值到文件名的映射
b_hash_to_name = {value: key for key, value in b_data.items()}
# 根据a.json中的哈希值顺序重新排列b.json中的数据
sorted_b_data = {b_hash_to_name.get(hash_value, hash_value): hash_value for hash_value in a_data.values() if hash_value in b_hash_to_name}
# 将重新排列后的数据保存到输出文件中
with open(output_file, 'w') as file:
json.dump(sorted_b_data, file, indent=4)
print(f"排列结果已保存到 {output_file}")
except FileNotFoundError as e:
print(f"文件未找到: {e}")
except json.JSONDecodeError:
print("JSON文件格式错误,请检查输入文件。")
except Exception as e:
print(f"发生错误: {e}")
实例
from 批量命名.函数.main import file_rename
from 哈希工具.哈希计算 import calculate_hash
from 哈希工具.哈希排序 import hash_sorting
target_directory = r"D:\Pictures\download\photos\image"
backup_directory = r"D:\Pictures\download\photos\backup"
start_file_prefix = ""
end_file_prefix = "image-"
valid_extensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']
length = 4
a_file = r'a.json'
b_file = r'b.json'
output_file = r'c.json'
# 调用函数
file_rename(target_directory, backup_directory, None, valid_extensions, length, mode='sequential')
calculate_hash(backup_directory, a_file)
file_rename(None, backup_directory, None, valid_extensions, length, mode='date_random_char')
calculate_hash(backup_directory, b_file)
hash_sorting(a_file, b_file, output_file)
评论区