#!/usr/bin/env python3 # -*- coding: utf-8 -*- """一文一夹整理(拷贝模式):子文件夹是新增逻辑,不 move、不进 backup。 权威原文默认仍在: docs/md_cursor/*_cursor.md docs/html_cursor/*_cursor.html 新增并行结构(拷贝): docs/md_cursor/<文档名>/<文档名>_cursor.md docs/html_cursor/<文档名>/<文档名>_cursor.html 规则: - 只 copy,永不 shutil.move - 不删除根目录文件 - 不删除、不搬迁「专题/」「作业/」「00_~08_*」等汇总夹 - 根目录有文 → 拷进一文一夹(根更新则覆盖夹内拷贝) - 仅夹内有、根没有 → 也拷一份到根(保持原件可见) """ from __future__ import annotations import shutil from pathlib import Path ROOT = Path(r"D:\workbuddy\192.168.110.207") MD = ROOT / "docs" / "md_cursor" HTML = ROOT / "docs" / "html_cursor" # 这些是汇总夹,不是「一文一夹」的文档名 SKIP_DIR_NAMES = { "assets", "backup", "00_索引与总纲", "01_Dify部署与排障", "02_Langfuse可观测", "03_LiteLLM与模型网关", "04_Higress总入口", "05_监控与SLA", "06_基础设施_K8s_GPU_Harbor_GitLab_ArgoCD", "07_实战作业", "08_架构培训与成长", "专题", "作业", "手册教程", "索引总纲", } README = """# 一文一夹(拷贝) 本目录是对应文档的**子文件夹拷贝**(新增浏览结构)。 - **权威原文**仍在上级目录的 `*_cursor.md` / 对应 `html_cursor` 根文件(以及历史汇总夹副本)。 - 整理脚本只 **copy**,不会 move 原文,也不会挪进 backup。 编辑建议:改根目录原文后重新运行 `organize_one_doc_one_folder.py`,或直接改本夹后再同步回根。 """ def doc_key(filename: str, suffix: str) -> str | None: if not filename.endswith(suffix): return None if filename.startswith("README_"): return None return filename[: -len(suffix)] def copy_if_needed(src: Path, dest: Path, *, prefer_src: bool) -> None: dest.parent.mkdir(parents=True, exist_ok=True) if not dest.exists(): shutil.copy2(src, dest) print("copy", src.name, "->", dest.relative_to(ROOT).as_posix()) return if prefer_src and src.stat().st_mtime > dest.stat().st_mtime: shutil.copy2(src, dest) print("update", dest.relative_to(ROOT).as_posix()) def ensure_readme(folder: Path) -> None: path = folder / "README_目录说明_cursor.md" if not path.exists(): path.write_text(README, encoding="utf-8") def collect_keys() -> set[str]: keys: set[str] = set() for p in MD.glob("*_cursor.md"): k = doc_key(p.name, "_cursor.md") if k: keys.add(k) for p in HTML.glob("*_cursor.html"): k = doc_key(p.name, "_cursor.html") if k: keys.add(k) for base, suffix in ((MD, "_cursor.md"), (HTML, "_cursor.html")): for folder in base.iterdir(): if not folder.is_dir() or folder.name in SKIP_DIR_NAMES: continue f = folder / f"{folder.name}{suffix}" if f.is_file(): keys.add(folder.name) return keys def main() -> int: keys = sorted(collect_keys()) print(f"[INFO] docs: {len(keys)} (copy-only, no move/backup)") for key in keys: md_root = MD / f"{key}_cursor.md" md_fold = MD / key / f"{key}_cursor.md" html_root = HTML / f"{key}_cursor.html" html_fold = HTML / key / f"{key}_cursor.html" # MD: 根 → 夹;若仅夹有 → 夹 → 根 if md_root.is_file(): ensure_readme(MD / key) copy_if_needed(md_root, md_fold, prefer_src=True) elif md_fold.is_file(): copy_if_needed(md_fold, md_root, prefer_src=True) ensure_readme(MD / key) # HTML 同理 if html_root.is_file(): (HTML / key).mkdir(parents=True, exist_ok=True) copy_if_needed(html_root, html_fold, prefer_src=True) elif html_fold.is_file(): copy_if_needed(html_fold, html_root, prefer_src=True) # 有 MD 无 HTML:留给 gen_all_html;有夹无根 HTML 时上面已处理 print("[PASS] one-doc folders synced by copy; originals left in place") return 0 if __name__ == "__main__": raise SystemExit(main())