Skip to content

Instantly share code, notes, and snippets.

@Lightblues
Created October 12, 2022 09:42
Show Gist options
  • Save Lightblues/c80533ffc29f901eecfd859eeb72abde to your computer and use it in GitHub Desktop.
Save Lightblues/c80533ffc29f901eecfd859eeb72abde to your computer and use it in GitHub Desktop.
Markdow文件增量同步. 用于笔记文件同步到个人博客.
#!/usr/local/bin/python3
""" @220325
增量同步. 根据 filename_map 所定义的文件映射, 增量同步md文件和图片文件夹.
需求: 在个人笔记中书写, 部分同步到个人博客. (前者实时更新, 后者仅作同步)
同步规则:
从下面定义 document_dir 同步到 technote_dir.
同步文件列表根据 filename_map.py 所定义
filename_map 格式例子
```python
filemap = {
"Python-note": ["420-Python", "Python"],
}
```
以下代码思路:
1. 构建 {文件夹: 路径} 的字典. 约束所有子文件夹不重名
2. 增量同步
3. 对应同步图片文件下, 对于没有的文件夹, 创建文件夹
"""
import os
import glob
import filecmp # 比较文件是否相同
import subprocess
# 定义了文件名映射, 例如 "Python-note": ["510-Python", "Python"],
from filename_map import filemap
# 定义同步文件夹 source, target
document_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
technote_dir = os.path.join(os.environ['HOME'], "Projects/z-blogs/techNotes/docs")
# basedir = "../../.."
# document_dir = f"{basedir}/PersonalNotes"
# technote_dir = f"{basedir}/techNotes/docs"
def get_dir2path(path, dir2path={}):
""" 构建 {文件夹名: 文件夹路径} 的map """
# for root, dirs, files in os.walk(path):
# for dir in dirs:
# if dir.startswith(".") or dir in ["meida"]:
# continue
# dir2path[dir] = os.path.join(root, dir)
for name in os.listdir(path):
# 遍历所有的目录 1. 非隐藏; 2. 非 media文件夹;
p = f"{path}/{name}"
if os.path.isfile(p):
continue
if name.startswith(".") or name in ["media"]:
continue
# md文件夹的条件: 其中有 md文件
items = os.listdir(p)
if len(items)==0 or any(i.endswith(".md") for i in items):
# 要求文件夹不同名!
assert name not in dir2path
dir2path[name] = p
# 递归
dir2path = get_dir2path(p, dir2path)
return dir2path
def incr_sync(name, src_dir, dest_dir):
# 增量同步
# 1. 文件
src = f"{doc_dir2path[src_dir]}/{name}.md"
dest = f"{tech_dir2path[dest_dir]}/{name}.md"
# 若目标 md 文件已存在, 检查是否完全相同
if os.path.exists(dest):
if filecmp.cmp(src, dest): return
# 比较 most recent content modification 时间
tsrc, tdest = os.stat(src).st_mtime, os.stat(dest).st_mtime
assert tdest<tsrc, f"{dest} is newer than {src}"
print(f"[sync] {name}")
subprocess.run(["rsync", "-av", src, dest])
# 2. 图片文件夹
src, dest = f"{doc_dir2path[src_dir]}/media/{name}", f"{tech_dir2path[dest_dir]}/media/"
if not os.path.exists(src): return
os.makedirs(dest, exist_ok=True)
subprocess.run(["rsync", "-av", src, dest])
if __name__=="__main__":
doc_dir2path = get_dir2path(document_dir, {})
tech_dir2path = get_dir2path(technote_dir, {})
for name, (src_dir, dest_dir) in filemap.items():
# 同步文件
incr_sync(name, src_dir, dest_dir)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment