迁移 Hexo 博客的终极解决方法

最后更新:
阅读次数:

声明: 本文的方法只针对了 Windows 10(64位)Macbook Pro(2017)(64位) 进行了测试,并不能保证其他系统也能起作用。

在 Windows 系统间、Mac 系统间、以及 Windows 与 Mac 之间迁移 hexo 博客时,会发生迁移后又重新生成的博客的文章与原来的博客的文章的时间不匹配,这是因为在将博客文件移动或复制的过程中,原文章文件的创建时间会统一变为一个新的时间,而 hexo 生成的博客文章的最初发表时间正是基于该文件的创建时间,所以博客迁移前后会出现文章时间前后不匹配的现象。

我的解决办法的总体思路如下:

  • 步骤一: 提取各个文章的数据,并存于文件中
    • 方法一: 通过 nodejs,从未迁移前的博客的 ./source/_post 目录下提取出各个文章的文章名、创建日期以及最后修改日期
    • 方法二: 直接在 GitHub 上面查看你博客仓库的 sitemap.xml 文件,并利用 nodejs 提取出各个文章的文章名、创建日期以及最后修改日期(这种方法尤其针对由于重装系统造成的博客文章时间丢失)
  • 步骤二: 对博客文件进行迁移(即将博客文章放到新的博客的目录下)
  • 步骤三: 利用步骤一提取的数据,恢复新目录下博客文章的创建日期与最后修改日期
    • 针对 Windows: 使用 Python 进行恢复(参考我之前的文章:换电脑之 hexo 博客重生记
    • 针对 Mac: 使用 nodejs 的 exec(),循环执行 touch 命令进行恢复
  • 步骤四: over,正常编译博客文件即可(hexo g

  • 使用 nodejs 获取各个文章的信息
// getBlogArticlesInfo.js

const fs = require("fs");

// 原始文章所在目录的路径
let path = "C:\\blog\\source\\_posts\\";

// 用来存储原始文章的信息(文件名,创建日期,最后一次修改日期)
let articlesInfoArr = [];

// 读取原始文章所在的目录
let fileArr = fs.readdirSync(path);

// 遍历返回的数组,过滤掉文件夹
fileArr.forEach(function(fileItem) {
let stats = fs.statSync(path + fileItem);

if (stats.isFile()) {
let obj = {};

obj.title = fileItem;
obj.birthTime = touchTimeStyle(new Date(stats.birthtime));
obj.lastModifiedTime = touchTimeStyle(new Date(stats.mtime));

articlesInfoArr.push(obj);
}
});

// 由于 touch 命令的 -t 定义的时间格式是 YYYYMMDDhhmm
// 所以下面这个函数利用传入的 Date 实例来生成这种格式的时间字符串
function touchTimeStyle(date) {
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
let hour = date.getHours();
let minute = date.getMinutes();

month = month < 10 ? "0" + month : month;
day = day < 10 ? "0" + day : day;
hour = hour < 10 ? "0" + hour : hour;
minute = minute < 10 ? "0" + minute : minute;

return "" + year + month + day + hour + minute;
}

// [..., { title: 'webpack-test.md',
// birthTime: '201703130800',
// lastModifiedTime: '201703130331' },...]
console.log(articlesInfoArr);

// 将数据存入文件,方便转移和存储
let targetPath = "./articlesInfo.json";
fs.writeFileSync(targetPath, JSON.stringify(articlesInfoArr));
  • 使用 nodejs 进行恢复
    • 注意: 以下代码在 Windows 上无法直接运行,因为 Windows 上没有 touch 命令
const fs = require("fs");
const { exec } = require("child_process");

// 读取 articlesInfo.json 文件,获取迁移前的文件的时间信息
let targetPath = "./articlesInfo.json";
let fileArr = JSON.parse(fs.readFileSync(targetPath));

// path 是迁移后博客文章所在的目录
let path = "./blog/source/_post/";

fileArr.forEach(function(file) {
let rebackCreateTime = `touch -t ${file.birthTime} '${file.title}'`;
let rebackModifiedTime = `touch -mt ${file.lastModifiedTime} '${file.title}'`;

// 通过 exec 函数执行 touch 命令
exec(
rebackCreateTime,
{
cwd: path
},
function(err, stdout, stderr) {
if (err) {
console.log(err);
}
console.log(stdout);
console.log(stderr);
}
);
exec(
rebackModifiedTime,
{
cwd: path
},
function(err, stdout, stderr) {
if (err) {
console.log(err);
}
console.log(stdout);
console.log(stderr);
}
);
});

以上代码中涉及到的路径均为我自己定义的路径,实际使用时还请结合你自己的路径进行设置。