2024-04-14 13:03:08
大家好,我是前端西瓜哥。
因为最近公众号没有涨粉,所以打算给我的个人博客网站(blog.fstars.wang)上的所有文章底部添加公众号的二维码。
为此我打算用 nodejs 写个批量处理文件的简单脚本。
我的具体需求是这样的。
文章都是用 markdown 文件写的,这是一种纯文本的文件格式,并且都位于 posts 文件夹下。
现在我们需要将 所有 markdown 文件的末尾都加上我的公众号二维码图片 ,即加上下面这种格式的内容。
其中有个模板文件,不需要添加图片,所以我们要设置一个 黑名单 。
此外 有些文章已经加了该图片,我们也需要将这些文章排除在外 ,防止文章出现两张相同图片。同时也能防止不小心多次执行脚本,导致不可逆的修改。
我们先看完整的代码。
我们先设置好要用到的几个变量,然后将它们全都放到文件开头。
放到开头是为了让我们在需要时快速修改,符合相关代码高内聚原则。如果这些变量流散在代码逻辑中,当我们要改配置时,就要找上半天。
这里我引入了 nodejs 内置的 fs 库。fs 指的是文件系统(File System),fs 库就是专门用来处理文件的这么一个库。
fs/promise 则是fs 的 promise 版,将原来 fs 方法的回调参数移除,然后返回一个 promise。
我们就用这个 promise 版的 fs,因为它能写出同步形式的代码,可读性会更好。
fs.readdir() 方法能够读取目录内容,返回一个字符串数组,里面是所有的文件名。
接下来我们就去遍历这个数组。这里有个 初学者容易犯的错误,就是会去使用 forEach 方法。
因为 forEach 是 for 循环的一层封装,会执行传入的回调函数。但 forEach 的这个函数并不是 async 函数,所以是无法等待 await 方法执行完的。
async 函数其实是挺新的特性,forEach 则是存在了很长时间,当时 forEach 并没有考虑 async 这种东西,为了兼容,以后也不会。
所以你需要使用原生的 for 循环方法。for 和 for...of 都可以。
然后我们检查一下文件名是否在黑名单中,如果在,跳过此轮循环,直接进入下一轮。
然后我们要将文件名、和它所在的目录名组合,生成一个绝对路径。
直接使用文件名是不行的,因为 脚本会以被执行时所在的工作目录进行路径计算的,文件名是个相对于指定目录的相对路径,相对工作目录不一定是正确的。
接着是使用 fs.readFile 读取文件内容,记住要将 encoding 设置为 'utf8',否则你会拿到一个二进制的内容。
如果文件中已经有图片了,就跳过。
否则在文件末尾通过 fs.appendFile 方法添加图片内容。
脚本写好了,我们准备执行了。
首先为了可以吃后悔药,我强烈建议你想将文件通过版本控制软件(如 git),先存一个档。当脚本配合得不是很好时,我们可以轻松愉快地回滚到修改前的版本。当然拷贝一份作为备份也行。
总之,备份很重要。
改改配置,然后执行。
成功!
大家可以去我的 blog.fstars.blog 看看,现在所有文章下都有这二维码图片了。