You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用os.walk扫描文件夹增量更新sqlite3保留自定义数据及修复父节点bug

解决方案

1. C盘根目录父节点异常Bug修复

Bug根本原因

路径匹配逻辑不一致:

  • 你存储到folder_list的根目录路径是带尾部反斜杠的C:\\
  • 匹配父节点时你对父路径做了rstrip("\\")处理,变成了C:,和存储的C:\\无法匹配,导致匹配失败,父节点赋值异常
  • 额外问题:你用字符串类型的node作为folder_list的key,且每次遍历folder_list匹配父节点的效率极低,扫描大目录时卡顿严重

修复方案

  • 统一路径格式:所有路径统一不带尾部反斜杠存储和匹配
  • 重构folder_list为路径到node的直接映射,匹配父节点O(1)完成,无需遍历
  • 根目录单独处理,明确指定父节点为0,避免匹配异常

2. 增量更新保留自定义字段实现

实现逻辑

  • 删掉DROP TABLE IF EXISTS Windows10语句,不再每次重建表销毁原有数据
  • 插入记录前先判断该路径是否已存在于数据库,仅插入不存在的新文件/文件夹记录,原有记录完全保留,自然不会覆盖你手动填写的Beginner Info等自定义字段
  • 程序启动时先从数据库读取已有路径和node的映射,同时读取当前最大node值,后续新记录从该值开始递增,避免node重复

3. 其他优化建议

  • 增加权限异常捕获:扫描C盘时很多系统目录无访问权限,增加异常捕获避免程序中途崩溃
  • 用os.path模块处理路径拼接、拆分,避免手动处理反斜杠的格式错误
  • 取消冗余的打印语句,扫描大目录时打印会严重拖慢速度
  • 可增加文件修改时间校验,后续可以识别已修改的文件做更新(如果需要的话)

修复后完整代码

import os
import sqlite3

def init_db():
    conn = sqlite3.connect('Win10.db')
    # 仅当表不存在时创建,不会破坏原有数据
    conn.execute('''CREATE TABLE IF NOT EXISTS Windows10 
            ("Node"             INTEGER NOT NULL,
            "Filename"          TEXT,
            "Path"              TEXT    NOT NULL UNIQUE,
            "Beginner Info"     TEXT    DEFAULT 'Info',
            "Intermediate Info" TEXT    DEFAULT 'Info',
            "Advanced Info"     TEXT    DEFAULT 'Info',
            "Tags"              TEXT    DEFAULT 'separated by whitespace tags',
            "Parent"            INTEGER NOT NULL,
            "isFolder"          INTEGER DEFAULT NULL,
            "fileExt"           TEXT DEFAULT NULL,
            PRIMARY             KEY("Node")
        )''')
    # 读取已有路径和node的映射,以及当前最大node值
    path_node_map = {}
    cursor = conn.execute("SELECT Path, Node FROM Windows10")
    for row in cursor:
        path_node_map[row[0]] = row[1]
    max_node = conn.execute("SELECT IFNULL(MAX(Node), 0) FROM Windows10").fetchone()[0]
    conn.commit()
    return conn, path_node_map, max_node

def scan_and_sync(root_path="C:\\"):
    conn, path_node_map, current_node = init_db()
    print("数据库初始化完成,当前最大Node值:", current_node)
    root_path = os.path.normpath(root_path)
    
    # 先处理根目录
    if root_path not in path_node_map:
        current_node += 1
        root_filename = os.path.basename(root_path) + "\\"
        conn.execute('''INSERT INTO Windows10 (Filename, Path, Parent, fileExt, isFolder)
                     VALUES (?, ?, ?, ?, ?)''', (root_filename, root_path, 0, "", 1))
        path_node_map[root_path] = current_node
        print("已添加根目录:", root_path)
    
    # 遍历目录树
    for dirpath, dirnames, filenames in os.walk(root_path):
        dirpath = os.path.normpath(dirpath)
        # 跳过已存在的目录
        if dirpath not in path_node_map:
            # 找父目录node
            parent_path = os.path.dirname(dirpath)
            parent_node = path_node_map.get(parent_path, 0)
            current_node +=1
            dir_filename = os.path.basename(dirpath) + "\\"
            try:
                conn.execute('''INSERT INTO Windows10 (Filename, Path, Parent, fileExt, isFolder)
                             VALUES (?, ?, ?, ?, ?)''', (dir_filename, dirpath, parent_node, "", 1))
                path_node_map[dirpath] = current_node
            except sqlite3.IntegrityError:
                # 并发插入冲突,跳过
                continue
        
        # 处理当前目录下的文件
        parent_node = path_node_map[dirpath]
        for filename in filenames:
            file_path = os.path.normpath(os.path.join(dirpath, filename))
            if file_path in path_node_map:
                continue
            # 获取后缀
            file_ext = os.path.splitext(filename)[1].lstrip(".")
            current_node +=1
            try:
                conn.execute('''INSERT INTO Windows10 (Filename, Path, Parent, fileExt, isFolder)
                             VALUES (?, ?, ?, ?, ?)''', (filename, file_path, parent_node, file_ext, 0))
                path_node_map[file_path] = current_node
            except sqlite3.IntegrityError:
                continue
    
    conn.commit()
    print("同步完成")
    conn.close()

if __name__ == "__main__":
    # 可以修改扫描路径,比如扫描D盘就传"D:\\"
    scan_and_sync("C:\\")

内容的提问来源于stack exchange,提问作者user16505976

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:12:04