
前阵子我终于把 NAS 上攒了三年多的笔记全部迁到了 Markdown。这个念头其实很早就有了但一直拖着直到某天我发现自己的知识库被拆成了四五个互不相通的角落——群晖 Note Station 里一大堆为知笔记里一些Docker 里的 Joplin 读不了 Note Station 的库Note Station 又导不出真正干净的 Markdown——那一刻我意识到再拖下去只会更痛苦。这篇文章是我完整迁移路线的复盘从为什么迁、怎么规划、如何清洗格式、图片怎么处理到迁移后怎么维护全部按实际操作记录你可以把它当成一份可以直接照着做的路线图。整个迁移过程花了我一个周末加上后面两周的零星清理。如果你手里的笔记量跟我差不多几百篇上下完全可以参考我的路线省掉中间试错的时间。1. 为什么从 NAS 笔记迁到 Markdown我的三个真实痛点1.1 私有格式的锁死效应NAS 上自带的笔记套件比如群晖 Note Station导出文件是.nsx格式。这种私有格式的好处是界面好看、开箱即用坏处是你只能在它的客户端里读。一旦客户端停止更新或者 NAS 系统大版本升级不兼容你的笔记就变成了盒子里的文件——数据明明还在但打不开。我见过更夸张的情况有人用某个老牌 NAS 笔记应用存了上千条笔记后来应用下架官方只提供一个导出工具导出来是一大堆 HTML 和 JSON普通用户根本不知道怎么还原成可读的文档。这种东西本质上就是数字时代的锁死效应——你写得越多沉没成本越高越不敢迁最后彻底被绑死在一家厂商的私有格式上。还有人虽然已经用 Markdown 存笔记了但喜欢直接往 NAS 共享文件夹里丢.md文件。这个思路没问题问题在于用 Windows 记事本打开发现换行全乱或者文件用了 GBK 编码导致中文乱码最后被迫换编辑器。这些乱象本质上都是格式不标准造成的。私有格式锁死的是你自己标准格式纯文本 UTF-8锁死的只有平台差异。1.2 一套知识被拆成 N 套工具记录工具一多知识就跟着分散。我的真实状态是工作内容放在为知笔记生活灵感写在 Note Station技术笔记在 Joplin还有一些散落在微信收藏、备忘录和邮件里。每次想找一条内容要在四五个地方分别搜一遍搜索结果还不一致有的支持全文检索有的只支持标题匹配有的中文分词稀烂搜都搜不到。这种状态最可怕的不是找不到而是它慢慢让你放弃了整理。因为整理的前提是所有东西在同一个地方现在连这个前提都不成立整理自然无从谈起。最后每次写笔记都变成一次漂泊今天这个工具顺手就用这个明天那个工具提醒弹出来又用那个。等回过神来知识库已经成了一片垃圾场。Markdown 是纯文本它天然不绑定任何工具任何编辑器都能打开。迁到 Markdown 等于把所有笔记先统一到同一个格式里然后用一个目录收拢再用一个工具检索。格式统一之后工具的选择就变成了纯粹的偏好问题而不是数据归属问题。1.3 Markdown 到底图什么Markdown 最核心的价值是可移植性。它的格式是公开的任何文本编辑器都能打开不会因为某个软件跨掉就废。哪怕你将来不打算用任何专业笔记软件直接用 VS Code 加一个文件树插件也能管理几百篇笔记。第二层价值是版本管理。Markdown 是纯文本天然适合 Git 做 diff每一次修改都能看到改动痕迹出了幺蛾子可以回滚。这一点是私有格式完全做不到的私有笔记软件最多给你一个历史版本功能而且通常有版本数量限制。第三层价值是生态。Markdown 的周边工具极其庞大从 Obsidian、Logseq到 VS Code、Typora再到静态博客 Hexo、Hugo全部原生支持。你写好的笔记随时可以变成博客、文档、知识库、演示文稿不需要二次转换。我整理了一个对比表格方便你直观理解对比维度私有笔记格式Markdown 纯文本格式开放性不公开依赖官方解析公开标准任意编辑器可读数据可迁移性导出格式千奇百怪复制粘贴即可迁移版本管理有限的历史版本或没有Git 完整 diff 与回滚工具绑定强绑定特定客户端零绑定工具随便换长期保存风险服务停摆即废纯文本几十年可读扩展玩法受限于官方 API博客、脚本、自动化任你折腾说白了Markdown 是笔记界的普通话。你不用它的时候不觉得一旦所有笔记都变成普通话你会发现整个世界都通了。2. 迁移前的总体规划先设计再动手千万别直接导出2.1 盘点现状你的笔记属于哪一类动手之前先清点别急着点那个导出按钮。我把自己手里的笔记来源分成了三类第一类是 NAS 自带笔记套件也就是 Note Station、备忘录这类。导出方式通常是.nsx压缩包里面可能有内嵌附件和图片需要在导出后做二次处理。第二类是 Docker 里的笔记服务Joplin、为知笔记、蚂蚁笔记都有。Joplin 可以直接导出 Markdown为知笔记需要客户端导出.zip再解包蚂蚁笔记的导出则可能是一堆带 JSON 元数据的内容。这一类来源不同导出后的干净程度差异极大。第三类是散落在共享文件夹里的富文本、Word 和纯文本。Word 可以另存为 Markdown也可以用 pandoc 转但转换后排版多多少少会有问题需要清洗。盘点的时候要做三件事第一统计数量知道自己大概要处理多少篇第二记录原格式方便后面按格式批量处理第三找出所有引用过的图片和附件因为这类文件最容易在迁移中丢失。我的习惯是建一个表格每一行写来源工具、导出格式、预估数量、是否含图片、备注这样后面每一步都有据可查。2.2 目标结构先想好文件怎么摆不要一上来就导出先设计目标结构。因为一旦几百个 Markdown 文件导出后散落在一个文件夹里再想重新整理就难了。我最终定的结构是notes/ ├── 0-inbox/ # 采集箱未整理的丢这里 ├── 1-projects/ # 项目类笔记 ├── 2-areas/ # 领域长期维护网络、存储、NAS、硬件 ├── 3-resources/ # 主题资源Docker、Markdown、工具链 ├── 4-archive/ # 归档不再活跃的内容 └── assets/ # 所有图片附件集中存放这个结构参考了 PARA 方法但按 NAS 场景做了微调。PARA 的核心是按行动属性而不是知识属性分类举个例子一篇群晖 Container Manager 镜像拉取失败的笔记如果按工作/生活/技术分类你会纠结该放哪里如果按 PARA 分类它属于当前正在排障的项目直接放进1-projects/排完障如果问题不再出现就归档到4-archive/整个过程毫不纠结。目录不必死板照抄但三个原则要把握第一必须有0-inbox/给那些来不及整理的碎片内容一个临时落脚点第二必须有归档目录否则所有笔记都堆在当前层级时间一长又乱了第三附件目录必须独立不能让图片散落在各个笔记文件夹里否则后面做备份和发布时想死的心都有。2.3 工具链只保留三类工具迁移期间不用装很复杂的工具链太多工具反而是负担。我实际用到的只有四样一个 Markdown 编辑器Typora 或 VS Code 都行用来查看效果、改 front matterpandoc用来把 Word、HTML、富文本批量转成 MarkdownPython配合正则表达式清洗导出的乱七八糟格式Git迁移前先把目标目录初始化成仓库每做完一步就提交一次防止误操作。工具贵精不贵多。有的朋友一上来就装 Obsidian 加二十个插件结果先被插件生态绑架了。我的建议是迁移阶段只把笔记当成一堆文本文件看待不要想太多预览、关系图谱、双向链接的事。让笔记先活成纯文本工具随时可以换反过来如果你先被某一款工具的插件生态套住那跟被私有格式套住也没什么本质区别。3. 导出与清洗把私有格式洗成标准 Markdown3.1 三种典型来源的导出方法先说最麻烦的群晖 Note Station。在 Web 端选中笔记点导出你会得到一个.nsx文件。它其实是一个 zip 包把后缀改成.zip再解压能看到 HTML、JSON 和 images 目录。HTML 再用 pandoc 转成 MarkdownJSON 里存的是标签和创建时间可以用来生成 front matter。这一步不能省因为 Note Station 没有官方的 Markdown 导出能力只能走HTML 中转这条路线。为知笔记稍微好一点。在客户端里全选笔记导出为.zip解包后直接就是.md文件加上附件目录。需要注意的是为知笔记导出的 Markdown 头部会有一些自定义的元信息比如author、created这些字段需要用脚本清洗成标准的前置格式。Joplin 是三个里面迁移成本最低的。直接在界面上选择 Export All格式选 Markdown导出的就是标准 md 文件图片放在_resources文件夹里。Joplin 还有一个好处是原生的 Markdown 编辑器所以很多笔记本身就是标准 md导出后几乎不需要清洗。如果你手里还有 Word 或富文本文件用 pandoc 一条命令就能转pandoc input.docx -t markdown -o output.md --extract-mediaassets--extract-mediaassets这个参数会顺手把 Word 里内嵌的图片抽到assets/目录非常省事。3.2 清洗一个 Python 脚本解决 80% 格式问题私有笔记导出的 HTML 转成 Markdown 后常见问题有多余的空行、神秘的a name.../a锚点、从网页复制的超长链接、标签被转成了#标签但中间带空格、标题层级混乱。我写了一个清理脚本主要做四件事去 BOM把 CRLF 统一转成 LF用正则去除 HTML 残留标签把# 标签统一成 front matter 里的 tags 字段统一标题层级只保留 h2/h3 及以下。脚本骨架大概是这样的import re from pathlib import Path def clean_md(text: str) - str: # 1. 去除 HTML 标签残留 text re.sub(r[^], , text) # 2. 合并连续空行 text re.sub(r\n{3,}, \n\n, text) # 3. 将行内类似“【标签】”的标记转成 tag 列表 tags re.findall(r【([^】])】, text) text re.sub(r【[^】]】, , text) # 4. 统一标题层级把 H4 降为加粗或列表 # 这里根据你的实际数据调整 return text for file in Path(exported).glob(*.md): text file.read_text(encodingutf-8) file.write_text(clean_md(text), encodingutf-8)这里要注意re.sub(r[^], , text)会误伤 Markdown 里的盘符这类文本比如 Windows 路径C:\ 提示符。所以更稳妥的做法是先全局搜索典型的 HTML 标签特征确认确实是 HTML 残留再批量删。清洗的目标不是一步到位完美。先让 80% 的笔记能打开、能读、搜索正常剩下 20% 手工调整。如果你在清洗阶段追求 100% 完美大概率会把自己耗死在繁琐的细节里最后半途而废。3.3 图片和附件最容易翻车的环节迁移完后最惨的结局是文字全回来了图片全部灰掉。图片问题分两种一种是图片被内嵌在私有格式里导出后散落各处另一种是 Markdown 里写的是相对路径但目录结构一变路径全部失效。我的解决办法是所有图片统一下沉到assets/目录文件名改成{note_id}-{original_name}避免重名然后用脚本批量重写图片引用路径。如果你手里图片数量不大bash 一行流也能解决# 假设 md 在子目录里图片统一放到 ../assets find . -name *.md -exec sed -i s|的引用解析路径检查文件是否存在不存在就根据文件名去附件目录里查找最后统一重写。这个过程很机械但一定要在迁移阶段做完因为等笔记开始每天使用时没人愿意翻来覆去改图片路径。我的另一个教训是图片文件名一定要避免中文和空格。中文文件名在部分 Web 服务器上需要转义空格在 Markdown 里会引起解析歧义比如容易断链。迁移时顺手把图片统一重命名为英文加日期能省掉后面一大堆编码问题。4. 目录结构与元数据让 300 篇笔记不靠搜索也能找到4.1 目录怎么分避免三套分法的冲突最初我试着按工作/生活/技术来分结果技术笔记横跨工作和生活怎么放都别扭。比如一篇Linux 挂载 NAS 存储的笔记既算技术又跟工作有关放工作感觉太窄放技术又丢失了场景。后来改成 PARA 之后逻辑一下就顺了。PARA 的核心是按行动属性而不是知识属性分类正在进行的工作放进 projects长期维护的领域放进 areas感兴趣的资料放进 resources不动的放进 archive。对 NAS 场景尤其适用——因为你的笔记里既有项目排查记录比如群晖容器拉取镜像失败又有长期积累的配置心得比如NAS 存储架构对比还有大量收藏的教程链接。按行动属性分类后每一个文件放哪里几乎不需要思考。如果你觉得 PARA 太抽象可以用一个更直观的标准去理解打开这个笔记的频率有多高每周都在更新的放 projects每月会翻一两次的放 areas偶尔查资料的放 resources半年没动过的放 archive。这套判断标准比任何理论都好用。4.2 YAML Front Matter给笔记做身份证每篇笔记顶部加一段 YAML 元数据这是我本次迁移做得最正确的一个决定。格式如下--- title: 群晖容器服务拉取镜像失败排查 date: 2025-01-15 tags: [NAS, Docker, 排错] source: Note Station 迁移 status: done ---有了 front matter后续用 Obsidian 或静态博客时就能按标签筛选、按日期归档source字段标明迁移来源万一原稿有问题还能回溯status字段能告诉你这篇笔记是待整理、进行中还是已完成。这些元数据在你只有几十篇笔记时感觉没什么用但一旦超过两百篇它就是检索系统的基石。写 front matter 时注意几个细节date不要用2025/01/15这种斜杠格式YAML 解析器在不同工具里表现不一致统一用2025-01-15tags建议用数组格式[Tag1, Tag2]不要用字符串逗号分隔因为 Obsidian 和 Hugo 对字符串标签的解析规则不一样。4.3 命名规范让文件名自己会说话文件名不要叫未命名1.md。我采用YYYY-MM-DD-slug.md的格式例如2025-01-15-docker-mirror-troubleshooting.md。好处是文件列表天然按时间排序而且不打开正文也大概知道内容。这里的slug我建议用英文或拼音不要用中文。原因有两个一是 Git 和 Web 服务器对中文路径支持虽然越来越好但偶尔还是会有编码问题二是如果你以后想发布成博客中文 URL 要做转义迁移成本就高了。当然如果你确定永远只在 Obsidian 这类本地工具里用中文文件名完全没问题这不是规定只是给将来的自己留条后路。我见过有人用20250115-docker-mirror-troubleshooting这种不带横杠的日期前缀在文件系统里排序效果一样但可读性差一点。如果笔记量特别大我建议在日期和 slug 之间加一个顺序号比如2025-01-15-001-docker-mirror.md这样做的好处是即便标题撞车文件名也不会冲突。5. 常见问题与排查实录5.1 图片路径在迁移后全部失效这是最多人踩的坑我自己也翻过两次车。症状很统一Markdown 文件打开后图片全是裂图。排查思路分三步先看引用路径是相对路径还是绝对路径再用脚本统计 md 中被引用的图片文件是否存在最后统一按新的目录结构重写路径。我实测最稳的做法是图片全部放assets/下md 里的引用写成相对路径比如。不要用/home/user/assets/xxx.png这类绝对路径因为整个 notes 目录一换机器就全废。也不要依赖 Obsidian 那种自动匹配附件的链接格式那不是标准 Markdown。另外一个隐蔽的坑是文件名大小写。Windows 上Image.png和image.png是同一个文件但 Linux 上它们是两个文件。如果你在 Windows 上编辑 Markdown 再同步到 NAS 或服务器引用路径的大小写一旦对不上图片就在 Linux 上裂了。所以迁移时最好统一小写文件名。5.2 换行与表格渲染差异Markdown 的换行是出了名的坑。很多从笔记软件迁出来的文本回车换行在 Typora 和老编辑器里显示不一致。原因是最初 Markdown 的换行规则是一个换行是空格两个换行才分段后来 CommonMark 等实现又改了行为。结果就是同一篇笔记在不同工具里看到的段落间距不一样。解决方案是迁移时把单个\n保留确保编辑器支持软换行如果你要发布到博客建议在最终渲染阶段开启渲染器的breaks: true选项而不是在文本里硬塞两个空格。千万不要在每行末尾手动加两个空格来强制换行那在多个平台上效果完全不同以后想清理都麻烦。表格也是一大重灾区。从 Word 或在线文档复制内容转成 Markdown 后经常出现表格列错位、分隔行丢失的情况。遇到这类问题我一般直接手工重建表格或者用 Markdown 表格转换工具把原始数据转成 CSV 再重新导入。别指望用正则把复杂的表格完全自动化修复投入产出比太低了。5.3 代码块、数学公式与 Mermaid 丢失如果你原来在 NAS 笔记里写了代码块导出后最常见的现象是代码块上下少了三个反引号的围栏标记。因为有些私有笔记软件在导出时把代码块转成了pre标签pandoc 转 Markdown 时又没保留围栏信息最终结果就是代码文本和正文混在一起。这类丢失很难靠脚本完全修复但有一个土办法先全局搜索classlanguage-...之类的 HTML 特征再批量补成围栏代码块# 全局搜索带语言标记的代码块 grep -rn language- exported/找到之后用编辑器多行替换把precode classlanguage-python替换成python对应的/code/pre替换成。如果遇到没有语言标记的代码块优先保底成text至少保证代码和正文是分开的。数学公式同理。Note Station 里的 LaTeX 是图片或 MathJax 渲染导出后可能变成图片没法还原成文本这部分只能手工补充。但如果你原来存的是$$...$$或$...$这样的纯文本数学公式迁移后还在只是要看渲染工具支不支持。Mermaid 图在部分笔记软件内部能渲染导出来就剩代码块但只要代码文本还在在支持 Mermaid 的工具里就能重新渲染。所以迁移前强烈建议凡是代码、公式、图表优先保证源文本模式完整保留能编辑比能预览重要得多。5.4 NAS 挂载同步时的文件锁问题迁移完之后有人习惯把 notes 目录放在 NAS 的 SMB 共享文件夹里直接编辑结果发现时不时出现文件冲突、编辑保存失败。原因通常是多设备同时打开同一个 md 文件加上 macOS、Windows 对 SMB 文件锁的处理不一致两台设备同时写一个文件就会产生冲突。我的做法是本地保留一个工作副本编辑完通过同步工具推回 NAS如果用同步盘建议关掉实时双向同步改成手动或定时单向同步。这样避免两边互相覆盖也比开着实时同步占用大量 NAS 资源要省心。顺带说一句如果你在配置 NAS 文件服务时遇到外网访问慢这类问题方向上是看路由器防火墙、IPv6 配置和 DNS 解析跟笔记用什么格式关系不大。笔记格式解决的是数据层问题网络链路解决的是传输层问题不要把两件事混在一起排查。这里还要提醒一个细节如果你用 WebDAV 挂载 NAS 目录来编辑 Markdown有些编辑器保存时会生成临时文件或锁文件这些文件在同步时会变成.DS_Store、~$xxx.md之类的垃圾文件。建议在 Git 仓库里加一个.gitignore把这些临时文件全部排除掉避免污染版本历史。6. 后续维护版本管理 自动同步 扩展玩法6.1 Git把笔记当代码仓库管理迁移完成后我的 notes 目录就是一个 Git 仓库。每次整理一批笔记就 commit 一次message 写清楚比如migrate note station export、clean tags and front matter、fix image paths。偶尔改坏了直接git checkout .回滚再也不用担心手工误删。如果 NAS 上有 Git 服务就把本地仓库 push 到 NAS 上作为远端备份我用的就是群晖的 Git ServerDocker 里跑 Gitea 也可以。这个习惯比任何笔记自动保存都稳因为你可以随时看到笔记的完整演变历史。比如三个月前你改了一篇笔记现在想看看最初的原稿直接git log找那次 commit 就能看到。这里有个小技巧commit 之前先看一眼 diffgit diff会高亮所有改动既能让你发现自己无意中改了不该改的内容也能帮你保持 commit 历史的干净。批量重命名文件时用git mv而不是mvGit 能正确记录重命名历史以后回溯不会被当成删除新增。6.2 同步NAS 继续当后端但换协议迁到 Markdown 之后NAS 并没有退休它从笔记应用服务器变成了文件存储后端。我目前用的是 WebDAV 和 SMB 双通道电脑用 SMB 直接访问共享文件夹手机端用 WebDAV 挂载再加一层定时 rsync 到本地磁盘做冷备。同步这件事我的建议是不要盲目追求双向实时。除非你用的是成熟工具比如 Syncthing否则一定要做单向备份。双向实时同步一旦发生冲突会同时污染两端的数据而且你往往在冲突发生很久之后才发现。我自己就经历过两台电脑同时编辑一篇笔记一段时间后同步工具生成了冲突副本两个文件内容各缺一半最后还是靠 Git 的历史记录救回来的。定期备份不是复制文件就完事了要做还原演练。你可以一个月把备份目录恢复到一台临时机器上打开几篇笔记测试文件是否完整。这个过程能暴露很多隐蔽问题比如 NAS 硬盘坏道、同步遗漏、增量备份脚本失效等。笔记丢了可以补但那种以为备份了实际上没备份的落差感经历过一次就再也不想经历第二次。6.3 网页剪藏与自动化Agent 技能是下一站Markdown 迁移完成之后最大的收益是你可以开始做自动化。比如最近大家聊的Agent 将网页保存成 Markdown 的技能本质就是把网页正文提取、清洗、转成 Markdown 并写入你的 notes 目录。这种玩法在私有格式笔记时代几乎不可能因为私有 API 不开放你根本没法让脚本往 Note Station 里批量写入内容。而在 Markdown 库上你可以用脚本甚至 Agent 自动给笔记打 tag、生成摘要、按规范重命名。我个人接下来想把剪藏流做成一个自动化的 skill复制链接 → 提取正文 → 转 md → 提交到 notes 的0-inbox/。这个流程全部自动化之后每天的笔记采集成本几乎为零你只需要定期去0-inbox/做一次归类和整理即可。自动化的前提就是数据格式标准化。如果你的笔记还是私有格式想接入任何自动化工具都得先走官方 API限制重重但 Markdown 纯文本没有任何限制脚本、爬虫、大模型工具链都能直接操作。这也是为什么我坚持认为 Markdown 迁移不是一次性的苦差事而是给未来几年铺路。最后说一点个人体会。我花了一个周末迁完笔记之后最大的改变不是工具变好看了而是我终于敢对笔记做删除和重构了——因为知道有 Git 兜底改坏了大不了回滚。如果你也在 NAS 上攒了一堆走不出来的私有笔记我的建议是别等到有时间再整理直接照着上面的路线图先导出再清洗先把格式变成 Markdown 纯文本后面的事都好说。迁移这个动作本身不性感但它带来的自由度只有做完那一刻才体会得到。