AstroPaper博客Git Hook:基于Markdown前置元数据控制modDatetime更新
解决AstroPaper博客pre-commit Hook的modDatetime更新逻辑问题
问题分析
- 原Hook在文章分多次提交时会反复更新modDatetime,不符合发布后仅更新修改时间的需求
- 尝试用sed+grep+awk提取frontmatter时,因旧版awk不支持
RS=语法导致报错
解决方案
以下是兼容多数系统、满足需求的完整pre-commit Hook脚本:
#!/bin/bash # 遍历暂存区中修改的Markdown文件 for file in $(git diff --cached --name-only | grep -E '\.md$'); do # 提取frontmatter里的draft值(兼容所有awk版本) draft_value=$(awk ' BEGIN { in_frontmatter = 0; draft = "" } /^---$/ { in_frontmatter = !in_frontmatter; if (!in_frontmatter) exit; next; } in_frontmatter && /^draft:/ { split($0, parts, /: */); draft = parts[2]; gsub(/["'\'']/, "", draft); # 去除值的引号 print draft; exit; } ' "$file") case "$draft_value" in "first") # 将draft: first替换为draft: false,更新暂存区 sed -i.bak 's/^draft: *["'\'']first["'\'']/draft: false/' "$file" git add "$file" rm -f "$file.bak" # 清理sed生成的备份文件 ;; "false") # 生成UTC标准时间,更新modDatetime字段 current_datetime=$(date -u +"%Y-%m-%dT%H:%M:%SZ") sed -i.bak 's/^modDatetime: .*/modDatetime: '"$current_datetime"'/' "$file" git add "$file" rm -f "$file.bak" ;; *) # draft为true或其他值,不执行任何操作 ;; esac done exit 0
脚本说明
- draft值提取:通过awk识别frontmatter块(
---包裹),精准匹配draft:行并提取值,自动去除引号(兼容draft: "first"或draft: first写法) - draft为'first'时:自动将状态改为
false并加入暂存区,跳过modDatetime更新 - draft为false时:生成符合AstroPaper要求的UTC时间,替换原modDatetime字段并更新暂存区
- 兼容性处理:sed使用
.bak备份文件避免跨系统差异,awk逻辑不依赖高版本特性,兼容多数Linux/macOS系统
使用步骤
- 将脚本保存为
.git/hooks/pre-commit - 赋予执行权限:
chmod +x .git/hooks/pre-commit
内容的提问来源于stack exchange,提问作者iamsimonsmale
相关产品推荐
相关产品推荐

