Obsidian 迁移到思源的踩坑之旅

本贴最后更新于 518 天前,其中的信息可能已经沧海桑田

上次用思源还是上次,大概在做终身会员活动的时候有过一个月体验,因为当时内核崩溃次数比较多,也有点卡(尤其是图谱)所以印象中思源的体验并不好。

这段时间跟别人推荐 Obsidian 和 Anytype 时被反向推荐了,于是再次安装试试看。


三步走(每一步都要做好备份)

  1. 正则替换图片链接
  2. 将创建时间替换为思源文件的 UID(这一步很慢
  3. 替换块 ID(可选,好像有点问题,但这一步挺快的,可以试试)

简单体验后认为思源的进步确实蛮大的,丝滑,稳定,决定从 Obsidian 换到思源。

当然,换笔记软件的第一步是尝试把整个 Ob 库迁移过去。

这里有几个点要注意:

  1. 虽然思源支持 Markdown 文件夹导入,但是思源对于链接的格式有一定要求。这个地方我试了好久,才在论坛上看见答案。

    1. 附件的格式需要是 md 链接 ![]()
    2. 内链的格式需要是 wiki 链接 [[]]
  2. 导入到思源的文件,创建日期根据文件的 UID 来判断,但 UID 是根据在思源中创建文件的时间来生成。

  3. 无序列表里的内链不能被转换


下面是解决前两步的方法

尝试前,建议先备份 OB 库文件,新开一个思源工作空间。
仅仅抛砖引玉,如果各位大佬有更好的办法,那你们就用更好的办法!


第一步 将附件的链接改为 md 链接

进行全局搜索替换,该方案来自 Obsidian 论坛,我增加了一些格式。

可以使用 vscode 等软件打开 ob 库文件夹(最好备份一下)使用 linter 插件应该也行,我没试。

搜索:

!(\[\]\(<*)(.*?)([.])(png|jpg|jpeg|bmp|gif|tiff|canvas|svg|webp|pdf|epub|gif|excalidraw|excalidraw.md|mp4|JPG|PNG|anyotherimagetype)(.*?)(?:\|.*?)*(?:#.*?)*\)

替换:

![](/$2$3$4)

第二步 更改思源中文件的 UID,以达到思源创建日期与 ob 定义的创建日期相同

效果:
image

步骤:

  1. 在 Obsidian 中使用 linter 等插件在 metadata 中添加 created,我的格式是 YYYY/MM/DD HH:mm:ss Z

    image

  2. 在思源中导入 markdown 文件夹,复制文件夹路径,然后关闭思源(最好关闭)

  3. 复制 python 代码(引导 GPT 生成的),将倒数第二行的文件夹路径替换为导入笔记的路径,然后运行。

    import os import re from datetime import datetime def extract_original_date(filename): match = re.match(r'^(\d{14})-', filename) return match.group(1) if match else None def extract_replace_date(content): match = re.search(r'created: (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) \+\d{2}:\d{2}', content) if match: created_date = match.group(1) dt_obj = datetime.strptime(created_date, '%Y/%m/%d %H:%M:%S') return dt_obj.strftime('%Y%m%d%H%M%S') def generate_new_uid(original_uid, replace_date): return original_uid.replace(extract_original_date(original_uid), replace_date, 1) def process_folder(folder_path): for root, _, files in os.walk(folder_path): for filename in files: if filename.endswith('.sy'): file_path = os.path.join(root, filename) with open(file_path, 'rb') as f: try: content = f.read().decode('utf-8') except UnicodeDecodeError: print(f"Error decoding file: {file_path}") continue replace_date = extract_replace_date(content) if replace_date: original_uid = os.path.splitext(filename)[0] new_uid = generate_new_uid(original_uid, replace_date) new_filename = new_uid + '.sy' new_content = content.replace(original_uid, new_uid) new_file_path = os.path.join(root, new_filename) os.rename(file_path, new_file_path) with open(new_file_path, 'w', encoding='utf-8') as f: f.write(new_content) # Replace original UID with new UID in other files for root2, _, files2 in os.walk(folder_path): for filename2 in files2: if filename2.endswith('.sy'): file_path2 = os.path.join(root2, filename2) with open(file_path2, 'rb') as f2: try: content2 = f2.read().decode('utf-8') except UnicodeDecodeError: print(f"Error decoding file: {file_path2}") continue new_content2 = content2.replace(original_uid, new_uid) with open(file_path2, 'w', encoding='utf-8') as f2: f2.write(new_content2) # 调用示例 folder_path = r'D:\笔记\SiyuanObsidian导入\data\20230816005055-be9q8kj\20230816025046-f1kqm5h' print(f"Processing folder: {folder_path}") process_folder(folder_path) print("Processing complete.")

等待转换完成,这个代码比较慢,它的原理是用 created 中的日期替换旧 UID 的日期形成新的 UID,然后全局搜索旧 UID 替换为新 UID。耐心等等。

‍替换块 ID

import os import re def collect_new_uids(folder_path): new_uids = [] for root, _, files in os.walk(folder_path): for filename in files: if filename.endswith('.sy'): new_uid = os.path.splitext(filename)[0] new_uids.append(new_uid) return new_uids def process_folder_with_global_new_uids(folder_path, new_uids): for root, _, files in os.walk(folder_path): for filename in files: if filename.endswith('.sy'): file_path = os.path.join(root, filename) with open(file_path, 'r', encoding='utf-8') as f: content = f.read() file_new_uid = os.path.splitext(filename)[0] block_ids = re.findall(r'\d{14}-[a-zA-Z0-9]{7}', content) for block_id in block_ids: if block_id not in new_uids and "Data\":\"assets/" not in content: new_block_id = file_new_uid[:12] + block_id[12:] content = content.replace(block_id, new_block_id) with open(file_path, 'w', encoding='utf-8') as f: f.write(content) # 调用示例 folder_path = r'D:\笔记\SiyuanObsidian导入\data\20230816005055-be9q8kj\20230816025046-f1kqm5h' new_uids = collect_new_uids(folder_path) process_folder_with_global_new_uids(folder_path, new_uids)
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    24877 引用 • 102372 回帖
1 操作
ACai 在 2023-11-01 23:13:47 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...