分页: 1 / 1

python-磁盘坏道chkdsk之后有很多文件打不开了,将能打开文件转移

发表于 : 2026-09-07 12:30
rungod

代码: 全选

import os
from tqdm import tqdm

# === 配置区域 ===
SOURCE_DIR = r"E:"  # 损坏磁盘中的源文件夹
DEST_DIR = r"F:\RescuedFiles"           # 健康磁盘中的目标文件夹
CHUNK_SIZE = 1024 * 1024        # 每次读写 1MB,防止大文件内存溢出
# ==================

os.makedirs(DEST_DIR, exist_ok=True)

print("🔍 正在扫描源目录,获取文件列表(这可能需要一点时间)...")
all_files = []
for root, _, files in os.walk(SOURCE_DIR):
    for file_name in files:
        src_path = os.path.join(root, file_name)
        # 自动跳过系统隐藏文件夹,只找你的真实文件
        if '$RECYCLE.BIN' in src_path or 'System Volume Information' in src_path:
            continue
        all_files.append(src_path)

total_files = len(all_files)
if total_files == 0:
    print("未找到任何有效文件,请检查源路径。")
    exit()

success_count = 0
fail_count = 0
skip_count = 0

print(f"📊 共发现 {total_files} 个有效文件,开始【全量移动】...\n")

# 使用 tqdm 包裹文件列表,显示实时进度条
for src_path in tqdm(all_files, desc="抢救进度", unit="个", ncols=100):
    rel_path = os.path.relpath(src_path, SOURCE_DIR)
    dest_path = os.path.join(DEST_DIR, rel_path)
    
    # 1. 断点续传:如果目标文件已存在且大小一致,则跳过
    try:
        if os.path.exists(dest_path) and os.path.getsize(src_path) == os.path.getsize(dest_path):
            skip_count += 1
            continue
    except Exception:
        pass

    # 2. 严格验证并【移动】文件
    try:
        os.makedirs(os.path.dirname(dest_path), exist_ok=True)
        
        # 边读边写,进行完整性校验
        with open(src_path, 'rb') as f_src, open(dest_path, 'wb') as f_dest:
            while True:
                chunk = f_src.read(CHUNK_SIZE)
                if not chunk:
                    break  # 文件完整读取完毕
                # 【核心验证】检查是否包含大量连续的空白字节(0x00)
                if b'\x00' * 1024 in chunk:
                    raise ValueError("检测到连续空白数据,文件底层已损坏")
                f_dest.write(chunk)
        
        # 3. 验证通过,【删除源文件】完成真正的移动
        os.remove(src_path)
        success_count += 1
        
    except Exception as e:
        fail_count += 1
        # 写入中途失败,删除目标盘上写了一半的残缺文件
        if os.path.exists(dest_path):
            try: os.remove(dest_path)
            except: pass

# 打印最终统计结果
print("\n" + "="*40)
print("🎉 抢救任务完成!")
print(f"成功移动: {success_count} 个")
print(f"损坏/失败: {fail_count} 个")
print(f"已存在跳过: {skip_count} 个")
print("="*40)