当前位置: 首页 > news >正文

Typora 笔记迁移 Obsidian 图片链接转换

附件:Typora 笔记迁移 Obsidian 图片链接转换

需求

将typora笔记库迁移到Obsidian,但是typora的图片使用的是严格markdown ![](),Obsidian是wiki ![[]]

笔记库文件夹下面有超级多的.md笔记,手动操作太慢了,因此采用Python进行处理,进行批量修改文章链接格式。

![Pasted image 20221223164738.png](./Database/Pasted image 20221223164738.png)---->![[Pasted image 20221223164738.png]]

由于Obsidian是wiki ![[]] 因此后面采用程序或手动方式,将所有的图片移动到Obsidian仓库下指定图片文件夹即可,例如asset

思路

1、检测该链接是否为图片?![](./Database/
2、正则表达式匹配,![](./Database/任意内容)
3、替换`![](./Database/任意内容)`为`![[任意内容]`---->`![[Pasted image 20221223164738.png]`

实践

备份整个目标文件夹,打压缩拷贝该文件夹副本进行操作。

参考目录

|-- 转换
|   |-- typora_to_obsidian.py
|   `-- 综合软件使用教程 # 目标文件夹
|       |-- Database

安装python,网上教程很多,不再赘述。

  1. 保存脚本: 将下面的代码保存为一个 .py 文件,例如 rename_md.py

  2. 运行脚本: 打开终端或命令行工具,进入你保存脚本的目录,然后运行它:

    typora_to_obsidian.py
    

    程序会提示您输入笔记库的文件夹路径。只需将文件夹的绝对路径复制粘贴进去,然后按回车键即可。
    image

  3. 检查结果: 脚本会自动扫描该文件夹及其所有子文件夹中的 .md 文件,并完成链接的替换。处理过程会显示在终端中。

检查

谨慎一下,要进行检查,打开修改后的任意.md笔记,在typora中进行正则表达式查找:
!\[([^\[\]]*)\]\(([^()]*)(\s+["'].*?["'])?\) 可见,下面没有被替换的均为网络链接格式和示范笔记。

手动将转换成功的.md笔记移动到Obsidian笔记库中的新的位置。
采用程序或手动方式,将所有的图片移动到Obsidian仓库下指定图片文件夹即可,例如asset
打开一篇笔记,可见正常显示。

image

因此,本次转换图片链接操作成功!

image

代码

Python代码

import os
import re
import sysdef convert_image_links(directory):"""遍历指定目录下的所有 Markdown 文件,并将 Typora 格式的图片链接转换为 Obsidian 格式。Typora 格式 1: ![](./some_folder/image.png)Typora 格式 2: ![alt-text](./some_folder/image.png)Obsidian 格式: ![[image.png]]"""# 支持常见的图片文件扩展名image_extensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'webp']# 构建正则表达式,用于匹配 Typora 的图片链接# 解释:# !\[.*?\]\(   : 匹配 "![",然后是任意数量的字符 (alt text),然后是 "]("# (?:.*/)?    : 匹配并忽略路径部分 (e.g., "./Database/")。#              (?:...) 是一个非捕获组。#              .* 表示任意字符,/ 是路径分隔符。? 表示路径是可选的。# (.*?)        : 捕获图片文件名 (非贪婪模式)。这是我们需要的核心内容。# \.           : 匹配文件名和扩展名之间的点。# ({})         : 将支持的图片扩展名插入正则表达式。# \)           : 匹配最后的 ")"pattern_str = r'!\[.*?\]\((?:.*/)?(.*?\.({}))\)'.format('|'.join(image_extensions))# 添加 re.IGNORECASE 标志以忽略扩展名的大小写image_pattern = re.compile(pattern_str, re.IGNORECASE)# 遍历指定目录for root, _, files in os.walk(directory):for filename in files:if filename.endswith('.md'):file_path = os.path.join(root, filename)try:with open(file_path, 'r', encoding='utf-8') as f:content = f.read()# 使用正则表达式查找并替换所有匹配的链接# sub 函数的第二个参数 r'![[\1]]' 中的 \1 代表正则表达式中第一个捕获组的内容,# 也就是我们需要的图片文件名 (e.g., "image-20250726104501340.png")new_content, num_replacements = image_pattern.subn(r'![[\1]]', content)if num_replacements > 0:# 如果发生了替换,则将新内容写回文件with open(file_path, 'w', encoding='utf-8') as f:f.write(new_content)print(f"处理文件: {file_path}")print(f"  -> 成功转换 {num_replacements} 个链接。")except Exception as e:print(f"处理文件 {file_path} 时出错: {e}", file=sys.stderr)print("\n所有文件处理完毕!")if __name__ == '__main__':# 提示用户输入要处理的文件夹路径# 在 Windows 上,你可以直接复制文件夹路径,例如: C:\Users\YourName\Documents\MyNotes# 在 macOS 或 Linux 上,路径类似: /Users/YourName/Documents/MyNotestarget_directory = input("请输入您的笔记库文件夹的绝对路径: ")if os.path.isdir(target_directory):convert_image_links(target_directory)else:print("错误: 您输入的不是一个有效的文件夹路径。", file=sys.stderr)

正则表达式代码

!\[([^\[\]]*)\]\(([^()]*)(\s+["'].*?["'])?\)

这个正则表达式 !\[([^\[\]]*)\]\(([^()]*)(\s+["'].*?["'])?\) 是用来精确匹配并提取标准 Markdown 格式的图片链接的各个部分的。

整体结构

这个表达式匹配的完整格式是: ![alt text](image_path "optional title")

它被分成了几个主要部分来分别捕获 alt text (替代文本)、 image_path (图片路径) 和 optional title (可选的标题)。

各部分详解

正则表达式部分 含义解释
! 匹配一个字面量的感叹号 !,这是 Markdown 图片语法的起始标志。
\[ 匹配一个字面量的左方括号 [。因为 [ 是元字符,所以需要用 \ 来转义。
([^\[\]]*) 第一个捕获组 (Group 1): • (...):定义一个捕获组,用于提取括号内的匹配内容。 • [...]:定义一个字符集。 • ^:在字符集 [] 内部表示“非”,即匹配任何不包含在后面的字符。 • \[\]:这里指的是 [] 这两个字符。 • *:表示匹配前面的字符集零次或多次。 作用:捕获方括号 [] 之间的所有内容,即图片的 替代文本 (alt text)
\] 匹配一个字面量的右方括号 ]
\( 匹配一个字面量的左圆括号 (
([^()]*) 第二个捕获组 (Group 2): • (...):定义捕获组。 • [^()]:匹配任何不是 (不是 ) 的字符。 • *:匹配零次或多次。 作用:捕获圆括号 () 之间的内容,即图片的 路径或URL (image_path)
(\s+["'].*?["'])? 第三个捕获组 (Group 3),且为可选部分: • (...):定义捕获组。 • ?:表示整个第三个捕获组是可选的(可以出现0次或1次)。 • \s+:匹配一个或多个空白字符(如空格)。 • ["']:匹配一个双引号 " 或一个单引号 '。 • .*?:非贪婪匹配。匹配任意字符 (.) 零次或多次 (*),但尽可能少地匹配 (?),直到遇到下一个模式。 • ["']:匹配一个结束的双引号 " 或单引号 '作用:捕获可选的图片标题 (title),它由空格和引号包围。
\) 匹配一个字面量的右圆括号 )

总结

  • !\[ ... \]: 匹配 ![alt text] 的框架。
  • (...): 括号内的部分是捕获组,意味着在查找替换时,你可以用 $1, $2, $3 (或 \1, \2, \3,取决于具体工具) 来引用这些捕获到的内容。
    • $1 对应 ([^\[\]]*),即图片的替代文本。
    • $2 对应 ([^()]*),即图片的路径。
    • $3 对应 (\s+["'].*?["'])?,即可选的、带引号的标题。

这个正则表达式可以准确地处理包含或不包含可选标题的各类标准 Markdown 图片链接,同时避免错误匹配嵌套的括号或格式不规范的文本。

注意事项

  1. 备份: 强烈建议在运行此脚本前,先备份你的整个文件夹。 文件重命名是一个不可逆的操作,以防万一出现非预期的结果。

参考

  1. [wiki链接和markdown链接 对比 互相转换](https://garden.czchx.cc/czc知识库/笔记/知识库搭建/1-obsidian笔记/子/wiki链接和markdown链接 对比 互相转换/)
  2. PKMer_Wiki 链接和 markdown 链接之间的转换
  3. 一文搞懂正则表达式 - 知乎
http://www.hskmm.com/?act=detail&tid=22264

相关文章:

  • Java 运行 Word 文档标签并赋值:从基础到实战
  • 词云组件
  • 2025 年超声波清洗机品牌最新权威推荐排行榜:龙门式 / 悬挂式 / 全自动等多类型设备厂家 TOP3 精选,助力企业精准选购
  • 树的统一迭代法
  • 2025 年冷却塔品牌最新推荐排行榜:玻璃钢冷却塔、闭式冷却塔、方型逆流式冷却塔优质厂家 TOP3 精选,赋能企业选购
  • DailyPaper-2025-9-30
  • Powershell 管理 后台/计划 作业(六)
  • 32. 最长有效括号
  • java17及以上版本如何抵御TemplatesImpl注入
  • 详细介绍:【C++实战(53)】C++11线程库:开启多线程编程新世界
  • 将图片某个区域批量填充白色(jsx代码)
  • 《初等数论(第四版,北京大学出版社,潘承洞,潘承彪著)》阅读笔记+心得
  • 完整教程:Word和WPS文字中的自动编号和文字间距过大怎么办?
  • markdown笔记文件批量打上时间戳
  • 251001
  • 微服务调整中心高可用设计:从踩坑到落地的实战指南(二)
  • NOIP2025模拟赛27
  • NOIP2025模拟赛28
  • 十月数据结构题没做
  • NOIP2025模拟赛30
  • 2025西安品牌新房,西安刚需新房,陕西优质新房住宅推荐,地建嘉信臻境,超2000㎡高端会所,满足多元化生活需求
  • 2025年未央区高端楼盘,西咸新区品质楼盘,西安高新品牌楼盘住宅口碑推荐,地建嘉信臻境周边配套丰富,教育医疗商业齐全
  • 2025西安高端新房,西安优质新房,西安品牌新房住宅推荐,地建嘉信臻境,沣东文商板块门户,享双地铁便利
  • 2025年西安洋房楼盘,陕西优质楼盘,西咸新区现房楼盘住宅口碑推荐,地建嘉信臻境超2000㎡高端会所,功能多样
  • Python 闭包的应用场景与实战案例
  • input() 函数
  • 如何确保CMS系统能够飞快响应用户请求?全面性能优化指南
  • 近期
  • Playwright MCP 的使用与调试技巧
  • 实用指南:零基础学AI大模型之LangChain-PromptTemplate