前言※
obsidian 是一款基于本地文件的笔记软件,所以笔记的多端同步是个问题,虽然官方推出了自己的同步服务,但是本着能自己解决就自己解决的态度,我自己研究出了一个比较完美的同步方案。
解决方案※
因为我用的是苹果手机,所以自然而然的考虑到了 icloud 同步这个方法。 在手机版 obsidian 上创建笔记库,在 windows 上下载 icloud,登录 icloud 账号,obsidian 选择在 icloud 中打开笔记文件。 经过如上操作之后就解决了同步问题,本篇完(并没有) ^8fe52d
起初我是通过这种方案,但是使用一段时间后发现,在写笔记的过程中,obsidian 经常弹出「文件被外部修改,正在合并」的提示,然后再 icloud 中就会出现若干个重复笔记。 类似这样:
而且写着写着经常会有几行笔记消失了。 所以以上几宗罪使 icloud 同步变得很难用。
真·解决方案※
自动同步 icloud 和本地※
为了解决上述问题,我写了一个自动同步的程序,使其每隔两分钟在本地文件和 icloud 中同步一次。 同步的代码如下:
def file_cmp(f1,f2):
res = filecmp.dircmp(f1,f2)
common_dirs = res.common_dirs
common_files = res.common_files
same_files = res.same_files
left_only = res.left_only
right_only = res.right_only
# 只有目标地址有的文件则直接删除
if right_only != []:
for i in range(0,len(right_only)):
_newpath = f2+"\\"+right_only[i]
if os.path.isdir(_newpath):
os.removedirs(_newpath)
else:
os.remove(_newpath)
# 共有但有不同的文件进行拷贝
if common_files != []:
for i in range(0,len(common_files)):
if common_files[i] not in same_files:
shutil.copy(f1+"\\"+common_files[i],f2+"\\"+common_files[i])
# 只有源地址有的文件和目录则直接拷贝
if left_only != []:
for i in range(0,len(left_only)):
if os.path.isdir(f1+"\\"+left_only[i]):
shutil.copytree(f1+"\\"+left_only[i],f2+"\\"+left_only[i])
else:
shutil.copy(f1+"\\"+left_only[i],f2+"\\"+left_only[i])
# 有共同目录则递归比较子目录
if common_dirs != []:
for i in range(0,len(common_dirs)):
file_cmp(f1+"\\"+common_dirs[i],f2+"\\"+common_dirs[i])
然后我们建立一个 while 循环,持续运行这段代码,并且监测时间,当时间超过 2 分钟后进行一次备份。
nowtime = time.time()
oldtime = nowtime + backuptime*60
while True:
nowtime = time.time()
if nowtime >= oldtime:
file_cmp(filepath1,filepath2)
oldtime += backuptime*60
文件同步就实现了,但是我的笔记是需要经常在不同的设备上打开的,所以在主程序中我们加入这么一行:
# 打开软件时先从目标地址拉取最新版本
file_cmp(filepath2,filepath1)
这样,当打开程序时,首先先拉取一次 icloud 上的笔记文件,之后就每隔 2 分钟向 icloud 中同步一次。
让 obsidian 和我的程序同步启动和关闭※
同步关闭※
思路是要让 obsidian 和我的程序同步关闭,则需要持续监听 obsidian 进程是否存在,如果 obsidian 进程不存在,则自动关闭程序。 代码如下:
# 监听某个进程是否存在
def checkprocess(processname):
plist = psutil.pids()
msgcode = 0
for pid in plist:
try:
if psutil.Process(pid).name() == processname:
msgcode = 1
break
else:
msgcode = 0
except Exception:
msgcode = 0
return msgcode
以上代码是用于监听某个程序是否存在,接着我们写一个方法,让 obsidian 关闭之后,程序过 140 秒之后再结束,这样就有充足的时间备份到云端,代码如下:
def delay():
while True:
if checkprocess("Obsidian.exe") == 0:
# 让程序延迟一会儿再执行,以便程序完成备份
time.sleep(backuptime*70)
os._exit(0)
然后在主函数中新建一个线程打开这个方法:
thread_it(delay)
现在就实现了当 Obsidian 进程关闭时,就自动关闭程序
同步启动※
我们将写好的程序打包成 EXE,这里我是用 pyinstaller 作为打包工具 在命令行中输入:
pyinstaller -F -w comfile.py
等待片刻,将 dist 中的 exe 文件拷到别的地方(方便你自己找到)。 假设你已经拷好了,在同一个目录下建立一个 txt,名称和后缀改成:"obsidian.bat",如下:
start "" "obsidian 的路径"
start "" "刚才的拷贝的 exe 的路径"
上面输入你自己的路径,保存。 接下来,还是在这个文件夹下的空白位置右键,新建一个快捷方式,在弹出的窗口中输入如下内容:
同样的,后面输入刚才创建的的 bat 文件路径,点击下一步。
这里命名为 obsidian.exe,点击完成,这时文件夹下就出现了一个「obsidian.exe」的快捷方式,为了更直观的操作,我们改一下他的图标,接着我们右键这个快捷方式,找到「更改图标」按钮,在弹出来的窗口中找到 obsidian.exe 的文件路径,点击确定。
到此,所有的操作完毕,你可以像其他快捷方式一样,将这个快捷方式拖到开始界面,任务栏或者桌面。并且,点击它会自动打开 obsidian 和文件同步程序,点开后,我们在任务管理里可以看到程序已经在运行了 当 obsidian 关闭时,该进程也会自动关闭,基本是无缝无感的操作体验。这样我的多端同步问题就解决了。
结语※
本篇是基于 icloud 方式进行同步,其实 icloud 还可以替换为坚果云或者其他的云盘软件。 如果不想使用云盘软件,那么在本文的基础上,你也可以搭建基于 webdav 的同步方案,如果有需要的话我可以再出一期 webdav 的笔记同步方案。