agentleFS
iAstroUnicorniAstroUnicorn/astro-skills/skills/safe-path-migration/SKILL.md

safe-path-migration

Skill0 starsChanged 4 months agoApache-2.0View on GitHub

根目录改名/移动后,安全批量更新全树绝对路径引用。只替换「路径形式」的旧根前缀,保留品牌语义名、GitHub URL、历史旧根引用;规避备份目录递归陷阱;用 robocopy /MIR 强制清空长路径深层残留。适用于任何「D:\OldRoot → D:\NewRoot」或「嵌套到新父目录」的目录重构。

  • Deletes or force-pushes

The file

Files
SKILL.md

safe-path-migration — 安全路径引用迁移

当需要重命名或移动一个被大量文件硬编码引用的根目录时,盲目全局替换 OldRoot → NewRoot 会破坏品牌语义、仓库 URL、历史文档。本技能给出经过实战验证的安全流程。

何时使用

  • 根目录改名(如 D:\OldRoot → D:\NewRoot)。
  • 目录整体迁移/嵌套(如把 A、B 两个顶层目录移入 D:\Parent\,变成 D:\Parent\A\…)。
  • 任何「大量文件含旧绝对路径、需重定向」的场景。

核心原则:区分三类字符串,绝不盲替

对扫描到的每个 OldRoot 出现,先判定类别:

  1. 路径形式 D:\OldRoot\… 或 D:/OldRoot/… → 按映射表替换(这是要改的)。
  2. 品牌语义裸名 OldRoot(不跟路径分隔符,如「OldRoot 平台」)→ 保留不动。
  3. 仓库/站点 URL github.com/user/OldRoot、username.github.io/OldRoot → 保留不动(由仓库名决定,不随本地文件夹变)。
  4. 历史旧根 D:\OldRoot_OldSuffix\…(不同字符串,如下划线旧命名)→ 保留不动(属历史记录)。

判定靠正则:只匹配 D:[\\/]OldRoot[\\/](要求紧接路径分隔符),天然排除上述 2/3/4。

步骤

  1. 枚举首段,建立证据化映射(不要猜): grep -rhoE 'D:[\\/]OldRoot[\\/][^\\/[:space:]"'"'"'()<>]*' ROOT | sed 's#...##' | sort | uniq -c 看 OldRoot/ 之后第一层目录是什么,据此决定每个首段重定向到哪:
    • 仍在原仓库内的 → NewRoot\同段
    • 已迁出的子目录(如 Assets、Workspace 等已移到别处的)→ 正确新位置
    • 已改名的子目录 → 新名称 映射必须最长优先(先匹配 Projects\SubProject 再匹配 Projects),避免短路。
  2. 写替换脚本(Python),要点:
    • 扫描多个 root(os.walk),EXCLUDE_DIRS = {'.git','.workbuddy','node_modules','__pycache__',...}。
    • 备份根目录必须放在所有扫描 root 之外(如 D:\_pathfix_backup\),且在 walk 中对含 _pathfix_backup 的子串做 dirnames[:] = [d for d in dirnames if '_pathfix_backup' not in d] 排除——否则备份副本会被自身递归,路径无限嵌套、崩溃。
    • 替换逻辑:对每行依次应用映射(路径分隔符 \ 与 / 都兼容);只改路径形式,品牌/URL/历史不动。
    • 默认 dry-run 打印报告;--apply 才写文件(写前 shutil.copy2 备份到树外)。
  3. 先 dry-run,人工核对报告:确认每条 + 新路径合理、无 + 行残留 OldRoot(残留必为历史 OldRoot_Suffix 之类,确认 benign)。
  4. --apply,然后复验: grep -rnoE 'D:[\\/]OldRoot[\\/]' ROOT | grep -v '/.git/' | grep -v '/.workbuddy/' | grep -v '_pathfix_backup' → 应为 0。
  5. 清理临时产物:删脚本、报告、树外备份、D:\_empty_del(若有)。

致命坑:长路径深层残留删不掉

rm -rf、Python shutil.rmtree、甚至 \\?\ 前缀在某些沙箱/虚拟化文件系统上会因 260 字符路径限制静默失败或报 WinError 123,导致损坏的嵌套备份目录删不净。 解法(已验证):用 robocopy /MIR 镜像一个空目录来清空——

python -c "import os; os.makedirs(r'D:\_empty_del', exist_ok=True)"
robocopy "D:/_empty_del" "<目标深层目录>" /MIR /R:0 /W:0 /NFL /NDL /NP
rm -rf "<目标深层目录>"
rm -rf "D:/_empty_del"

robocopy 是 LongPathAware,能删穿深层嵌套。空目录源用 Python 在目标盘建(避免 Git Bash /tmp 映射问题)。

第二轮迁移(嵌套到新父目录)

当把 A 和 B 移入 Parent(Parent\A\…、Parent\B\…)时,映射变为:

  • D:\A\… → D:\Parent\A\…
  • D:\B\… → D:\Parent\B\… 注意是二级路径 Parent\A\…,不是旧根 Parent\… 直接裸用。复用本技能的脚本时仅需改映射表与 root 列表(root 改成 D:\Parent 或分别扫 D:\A、D:\B)。

不适用 / 注意

  • 工具自动生成的运行产物(runs/latest/*.json 等)内的旧路径,属重算产物,不手改。
  • 私有仓库内的历史/结构文档若把旧根作为「历史记录」叙述,按类别 4 保留。
  • 改完后务必 git status 确认改动面符合预期。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.