前言
之前我曾写过一篇关于使用 NPM 和 Shell 管理 Hexo 博客的文章,点击这里跳转。虽然那是我的第一篇文章,写得不是很完善,但脚本还是可以用的。最近我将博客平台切换到了 Hugo,因此决定对内容进行重构,以便更好地适应新的平台。
正文
大概的思路其实没有变,都是简化命令的输入。
先写一个 case 语句:
1
2
3
4
5
6
7
8
9
10
11
12
13
| #!/bin/bash
case $1 in
new)
echo "new blog"
;;
push)
echo "push blog"
;;
*)
echo "unknown option"
exit 1
;;
esac
|
new 这个分支主要是调用hugo new content [path]
生成 md 文件,需要解决根据传入的标题变量自动生成路径和文件名重复。
文件路径为了兼容就沿用之前的吧:content/posts/[yyyymmdd]/[title]/[hash-12].md
。
时间类似于:20240720,使用date +"%Y%m%d"
标题为了省事直接限定只能包含大小写字母和-
,使用grep -Eq '^[0-9a-zA-Z-]+$'
,-E
表示正则匹配,-q
表示静默模式,通过返回的状态码判断是否匹配,匹配返回0,不匹配返回1
文件名为了保持之前的风格,使用dd if=/dev/urandom bs=1 count=6 2>/dev/null | od -An -tx1 | tr -d ' '
,它会生成12个随机字符串
时间加上随机值大概率是不会出现重复的,为了避免意外导致文章被覆盖,可以使用if
语句和-e
选项来判断:
1
2
3
4
5
| # 抽取为一个函数
if [ -e "path"]; then
# 存在 重新生成文件名 递归调用自己
else
# 不存在 调用hugo new
|
难点在于函数的拆分和递归出口条件的判断,实现以下函数:
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
| # 函数:检查标题是否合法
check_title() {
echo "$1" | grep -Eq "^[0-9a-zA-Z-]+$"
}
# 函数:生成随机文件名
generate_random_filename() {
echo $(dd if=/dev/urandom bs=1 count=6 2>/dev/null | od -An -tx1 | tr -d ' ')
}
# 函数:根据标题生成完整路径
generate_path() {
local title=$(echo "$1" | tr ' ' '-')
local random_filename=$(generate_random_filename)
local date=$(date +"%Y%m%d")
echo "content/posts/$date/$title/$random_filename.md"
}
# 函数:创建博客文件,处理递归的出口条件
create_blog_file() {
local title="$1"
local path=$(generate_path "$title")
# 如果文件已经存在,则递归调用自己
if [ -e "$path" ]; then
create_blog_file "$title"
else
# 文件不存在,创建文件
hugo new content "$path"
fi
}
|
这样只需要在 new 分支调用check_title
和create_blog_file
就可以了:
1
2
3
4
5
6
7
8
9
10
| ...
new)
if check_title "$2"; then
create_blog_file "$2"
else
echo "标题格式:只能包含大小写字母,数字,-"
exit 1
fi
;;
...
|
而 push 分支需要做的就是 add + commit + push,这里会有一个问题,如果开着代理的话是 push 不上去的(不知道是不是节点的问题),而本地仓库已经有一条 commit 记录了,这时候需要git reset
再git commit
,特别的麻烦,为了保持远程仓库提交记录的干净,需要使用git log origin/main..HEAD --oneline
来判断本地是否存在已经提交但未推送的记录,如果有则输出不为空,完成 push 分支:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 函数名:add + commit + push
acp(){
git add .
git commit -m "update:blog $(echo $1 | tr ' ' '-') $(date +%Y%m%d)"
git push
}
...
push)
# wc -l 获取输出的行数
unpushed_commits_count=$(git log origin/main..HEAD --oneline | wc -l)
if [ "$unpushed_commits_count" -gt 0 ]; then
git reset --soft origin/main # TODO: mixed soft hard 区别
acp "$2"
else
acp "$2"
fi
;;
...
|
后记
Shell 脚本还是挺好玩的,前提是不出 bug 哈哈哈