背景
之前好几年都在用 mac OS 平台,除了因为 mbp 触控板非常舒适,不用另外用鼠标之外,还有一个最重要的原因是技术笔记都记录在了 Quiver 中,而这个笔记软件只有 mac OS 平台上有。若将工作平台换成 windows,就无法使用当年积累的笔记。(尽管 Quiver 也能导出 md 笔记,但在别的 markdown 编辑器中,想让图片分门别类放好,并让图片链接在笔记中正常显示是个挺大的问题。
去年入了外置键盘 hhkb 后,再用 mbp 的触控板就比较鸡肋了,因此也配了罗技的无线鼠标。相应地,继续使用 mac OS 的理由就少了 50%。再加之后面笔记软件换成了 typora + obsidian,现在工作平台基本已经换成了 win 11。
而当年搁置在 Quiver 中的技术笔记,一直都没空去做迁移,在 windows 上用 vm ware 装了个 mac OS 虚拟机专门用来必要时查看当年的放在 Quiver 中的笔记。
最近终于打算来一次彻底地和 mac OS 说 byebye 了,也顺带整合好一直以来的笔记。
手动迁移逐个调整图片链接是不可能的,所以掏出了久未使用的 python,写了一个小脚本,马马虎虎,反正能用就行。
解决思路 & 最终实现
Quiver 导出的 md 笔记不会有任何文件夹层级,所有文件中用到的图片链接都会被放到 resources 文件夹中。
这次图片链接的处理目的是:
- 如果这个 md 文件包含图片链接,就创建一个
同名+.assets
文件夹 - 修改该 md 文件中的图片链接:resources/xxxx.jpg —>
同名+.assets
/ xxxx.jpg - 将resources中的该 md 文件包含的链接图片移动到
同名+.assets
文件夹中(对于多个md文件共用一张图的链接要做特殊的处理)
最终实现能在 typora 与 obsidian 中同时正常显示这些笔记的图片。
python 代码
"""此程序用于迁移 quiver 中记录的笔记到 typora 或 obsidian 时,图片链接的批量修改。"""
"""
痛点:
quiver 导出的 md 笔记,会将所有文章中的图片放到 resources 文件夹下,而我使用 typora 的习惯是,将 md 笔记文件中包含的图片文件分别放到 “该md笔记文件名.assets” 文件夹下。
目的:
1. 找出 quiver 导出的 md 文件中包含图片的文件,分别创建 “该md笔记文件名.assets” 文件夹;
2. 将 resources 文件夹中对应的图片移动到对应的笔记文件夹中
3. 修改 md 文件中引用图片的链接指向移动后的图片文件位置,使得用 typora 打开该 md 文件时,可以正常显示图片。
事前准备:
1. 创建一个新的文件夹 "workshop"
2. 将 quiver 导出的笔记文件夹(md方式导出)放到这个 "workshop" 文件夹下
3. 在 "workshop" 文件夹下创建此 py 程序文件
py程序操作步骤:
1. 导入 md 文件
2. 如果找到 ![image],则如果不存在该文件的同名资源文件夹则创建“文件名.assets"文件夹
3. 找到每个 ![image],将“resources“改为 “文件名.assets“,并取出“xxxx.jpg”
4. 在 resouces 文件夹找到 “xxxx.jpg” 将其移动到 “文件名.assets” 文件夹中
"""
import os,re,shutil
note_dir = "Python_md" # quiver 导出的文件夹
work_dir = os.path.join(os.getcwd(),note_dir)
logfile = open("log.txt",'w',encoding="utf-8")
for md_file in os.listdir(work_dir):
if md_file.endswith('.md'):
file_dir = os.path.join(work_dir,md_file)
doc_dir = file_dir[:-2]+"assets"
with open(file_dir,"r",encoding="utf-8") as m_file:
print('\n\n==================== '+md_file+' processing ====================\n\n')
print('\n\n==================== '+md_file+' processing ====================\n\n',file=logfile)
data = m_file.read()
if re.search(r'!\[.*?\]',data,re.I):
# 创建文件对应的附件文件夹
if not os.path.exists(doc_dir):
os.makedirs(doc_dir)
search_text = 'resources'
# 修改文件中的图片链接地址
with open(file_dir,'r',encoding="utf-8") as m_file:
ori_word = r'\]\(resources/'
sub_word = ']('+os.path.basename(doc_dir)+'\\\\'
data = m_file.readlines()
xdata = ''
for idata in data:
idata = re.sub(ori_word,sub_word,idata,re.I|re.M)
idata = re.sub('\.jpg[\s=][=].*?\)','.jpg)',idata)
idata = re.sub('\.png[\s=][=].*?\)','.png)',idata)
xdata = xdata + idata
data = xdata
with open(file_dir,'w',encoding="utf-8") as m_file:
m_file.write(data)
# 将文件链接的图片移动到对应的附件文件夹中
match_word = '!\[.*?\]\(.+?\.assets\\\\(.*?)\)'
with open(file_dir,'r',encoding="utf-8") as m_file:
data = m_file.read()
new_pic_list = re.findall(match_word,data,re.I|re.M)
for pic in new_pic_list:
old_path = os.path.join(work_dir,search_text,pic)
new_path = os.path.join(work_dir,os.path.basename(file_dir)[:-2]+'assets',pic)
if os.path.exists(old_path):
shutil.move(old_path,new_path)
else:
print("cannot find "+old_path)
print("cannot find "+old_path,file=logfile)
for search_dir in os.listdir(work_dir):
if os.path.isdir(os.path.join(work_dir,search_dir)): # 逐个进入文件夹去找图片
old_path = os.path.join(work_dir,search_dir,pic)
if os.path.exists(old_path):
if old_path != new_path:
shutil.copyfile(old_path,new_path)
print("Problem fixed.Picture is found in another directory.(old: "+old_path+" new: "+new_path)
print("Problem fixed.Picture is found in another directory.(old: "+old_path+" new: "+new_path,file=logfile)
break
else:
print("Problem fixed.Picture already exists.")
print("Problem fixed.Picture already exists.",file=logfile)
# else:
# print('===cannot find '+os.path.join(work_dir,search_dir)) # md文件
# 修改文件链接图片的地址\ 为 /,以便 obsidian 的插件能读取图片
with open(file_dir,'r',encoding="utf-8") as m_file:
ori_dir = ''
for i in os.path.basename(doc_dir):
if i in '()[]?*+':
i = '\\'+i
ori_dir = ori_dir + i
ori_word = '\]\('+ori_dir+'\\\\'
sub_word = ']('+os.path.basename(doc_dir)+'/'
data = m_file.readlines()
xdata = ''
for idata in data:
idata = re.sub(ori_word,sub_word,idata,re.I|re.M)
xdata = xdata + idata
data = xdata
with open(file_dir,'w',encoding="utf-8") as m_file:
m_file.write(data)
print('done processing '+md_file+' !')
print('done processing '+md_file+' !',file=logfile)
logfile.close()
print("job done!")