Apin

blogs

自动化hexo中.md和.yml配置文件的版本管理

此文章属于原创,如需使用请标明出处!


为了记录学习过程,我在 gitpages 上搭建了一个 hexo 生成的静态博客网站。在学习过程中,我在一个本地文件夹中存储 md 文件和图片。到了要发布的时候再把它复制一份到 hexo 源文件夹里,用来渲染生成博客页面。由于图片加载的原因,本地 Markdown 文件夹和 hexo 源文件夹的 md 文件内容不同(没有使用图床)。

总结:同一篇 md 笔记,一份在本地 Markdown 文件夹,一份在 hexo 的源文件夹。我希望可以利用 bat 文件自动备份专门用来给 hexo 渲染的 md 文件和一些重要的 yml 配置文件,并上传至 github 仓库进行版本管理。


在接下来,我会一步步写下我自己设计 bat 的思路和过程。


源码

在这一部分将贴出源码。

我一共写了三个 bat 文件——ori_buildori_keep 和 ori_git。分别实现了创建ori_data目录,实现了备份 md 文件和 hexo 的相关配置文件,提交文件到 github 远程仓库。

  • pause 是一条命令,作用就是使程序暂停,这就是输出“请按任意键继续…”的原因。
  • @echo off 执行以后,后面所有的命令均不显示,包括本条命令。
  • echo off 执行以后,后面所有的命令均不显示,但本条命令是显示的。

注意:由于在bat里用的都是相对路径,这三个 bat 文件要放在 hexo 根目录下。


ori_build

ori_build 中,主要使用 md 创建文件夹,来构建目录结构。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@echo off

set f1=ori_data
set f2=tags
set f3=themes
set f4=posts
set f5=categories
set f6=demo
set f7=scaffolds
set f8=about

if exist %f1% (
echo "ori_data has exist"
cd %f1%
) else (
md %f1%
echo "ori_data built"
cd %f1%
)
if exist %f2% (
echo "tags has exist"
) else (
md %f2%
echo "tags built"
)
if exist %f3% (
echo "themes has exist"
) else (
md %f3%
echo "themes built"
)
if exist %f4% (
echo "posts has exist"
) else (
md %f4%
echo "posts built"
)
if exist %f5% (
echo "categories has exist"
) else (
md %f5%
echo "categories built"
)
if exist %f6% (
echo "demo has exist"
) else (
md %f6%
echo "demo built"
)
if exist %f7% (
echo "scaffolds has exist"
) else (
md %f7%
echo "scaffolds built"
)
if exist %f8% (
echo "about has exist"
) else (
md %f8%
echo "about built"
)

pause

ori_keep

ori_keep 中,使用 copy 和 xcopy 实现文件复制,两者间是有区别的,将在下面解释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@echo off
copy _config.yml ori_data\config.yml /y /v

xcopy source\_posts\* ori_data\posts /y /e /f
xcopy source\categories\* ori_data\categories /y /e /f
xcopy source\tags\* ori_data\tags /y /e /f
xcopy source\demo\* ori_data\demo /y /e /f
xcopy source\about\* ori_data\about /y /e /f
xcopy scaffolds\* ori_data\scaffolds /y /e /f

cd ori_data\themes
del * /Q
cd ..
cd ..

cd themes
for /d %%i in (*) do (
copy %%i\_config.yml ..\ori_data\themes\"%%i"_config.yml /y /v
)

pause

ori_git

ori_git 中,假设本地仓库与远程仓库一致,使用 git 命令提交更新。

1
2
3
4
cd ori_data
git add *
git commit -m "a commit"
git push -u origin main

设计

我会根据我一开始的设计思路进行解说。


ori_keep

keep 有维护的意思,即备份维护。


第一步:备份 _config.yml

很容易发现,源文件夹和目标文件夹有很明显的映射关系,只要遍历所有文件,将每一个目标文件复制到目的地就可以了。

第一条使用的是,copy

1
copy 源路径 目标路径

这里要提一点,就是 copy 文件过去,你绝对要面对一个问题,即文件覆盖(已经存在一个文件名一样的文件),你需要在文件复制前确认。由于我们是批文件处理,这种行为完全没必要,甚至破坏了 bat 文件的特性。

解决办法就是加上一个参数 /y ,意思就是 覆盖现有目标文件不需要确认,而参数 /v 的意思是 检查文件写入是否正确。

这样子,第一条复制根目录 _config.yml 的 copy 命令完成。

在 copy 目标路径中,最后一部分是 config.yml
这就是 copy 命令的特别之处,在复制文件的同时,重命名文件。


第二步:备份 md 文件和图片

在 md 和图片备份中,copy 命令是不能复制文件夹的,因此要使用 xcopy 文件。

命令的结构是完全相同的,只不过参数有变化。/y同上;/e复制所有的目录和子目录(包括里面的文件);/f显示完整的源和目标文件。

于是,实现了文章以及图片的备份,以及 tags 和 categories 模板的备份。

注意:通配符 * 表示多个字符。? 表示一个字符。


第三步:备份主题的配置文件

相对来说,这一部分是最复杂的一部分。

1
2
3
for /d %%i in (*) do (
copy %%i\_config.yml ..\source\ori_data\themes\"%%i"_config.yml /y /v
)

首先,我们需要了解 for 循环:

for [参数] %%变量名 in (匹配符) do (执行的命令)

  • 无参:遍历当前路径下的文件,可在(匹配符)中指定路径
  • /d:遍历当前路径下的文件夹,可在(匹配符)中指定路径
  • /r [路径]:深度遍历指定路径下的所有文件,子目录中的文件也会被遍历到,如果没指定路径,默认当前路径
  • /l:当使用参数 /l 时,需结合(匹配符)一起使用,此时 () 括号内部的用法规则为:(start, step, end),此时的 for 命令作用等同于 java 语言中的 for 语句
  • /f:用于解析文件中的内容

我的目的就是遍历 themes 的所有主题文件夹,并备份其配置文件。

变量名指向了每一个遍历的对象,在这里它指向了每一个主题文件。

第一步,进入 themes 文件夹,以便使用 for 进行遍历。
第二步,使用 copy 命令复制主题的配置文件。文件重命名部分是 "%%i"_config.yml,使用双引号将变量包裹,表示一个字符串。.. 表示返回上一目录。

注意:由于重命名命令 ren 没有覆盖文件的功能,因此不使用 xcopy+ren 实现配置文件的备份,要不然会出现报错。


ori_build

build即建立,建立 备份文件目录结构。


第一步:设置变量

set 变量名 = 变量值

在接下来的 if 分支结构中,要被判断 得是变量而不是字符串(实践所得)


第二步:建立文件夹

bat里的分支结构 if:

1
2
3
4
5
6
if exist %f5% (
echo "categories has exist"
) else (
md %f5%
echo "categories built"
)

和很多高级编程语言相似,结构相当明确。

exist 存在的意思,之后的变量需要使用 % 包裹——表示这是一个变量,和环境配置一样。


ori_git

首先将所有文件放入到暂存区,接着提交暂存区的文件到本地仓库,最后同步至远程仓库。


就这样,我成功实现了自动化,舒坦~