7 月 10 日,我无意间看到卡瑟布尔在动态里晒出了他用 Wallpaper Engine 捣鼓的随机二次元壁纸,画面切换得行云流水,每一张都赏心悦目。这场景一下子勾起了我的回忆——自从全面转向 macOS 工作流之后,我已经很久很久没有碰过那些花里胡哨的随机壁纸软件了。倒不是说 macOS 的默认壁纸不好看,只是日复一日面对同一张静态图片,难免有些审美疲劳。回想以前在 Linux 环境下,我倒是亲手写过简单的脚本来实现壁纸轮换,无非是调用 fehnitrogen 配合 cron 定时任务,逻辑清晰得很。可 macOS 毕竟是个封闭得多的系统,我不确定它的命令行工具是否支持动态更换桌面背景,更不确定有没有类似 Linux 下那种直接可用的接口。

抱着试一试的心态,我决定先向 AI 打听一下可行性,看看这条路到底通不通。它很快就给出了肯定的答复——macOS 确实可以通过命令行更换壁纸,只需借助一个叫 desktoppr 的小工具即可,而且这个工具可以通过 Homebrew 轻松下载安装。这样一来,整个流程就变得异常简单了:无非是下载一张随机壁纸,然后每隔一段时间自动更换一次。至于具体的时间间隔,完全可以根据个人喜好自由设定,无论是半小时、一小时还是更久都行。于是我开始动手写一个 Shell 脚本,逻辑大致如下:先用 desktoppr 把当前壁纸保存下来作为备份,然后指定一个专门存放壁纸的目录 ~/.Wallpaper,再设定切换间隔为 30 分钟。

脚本启动时会先检查目录是否存在,不存在则自动创建。为了应对中途退出,我特地加了 trap 来捕获 Ctrl + C 信号,确保退出时能恢复之前的壁纸。主循环里用 wget 从一个随机壁纸接口下载图片,以当前时间戳命名,然后调用 desktoppr 切换,最后进入 sleep 等待下一轮。整个过程干净利落,没有什么多余的开销:

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
#! /bin/zsh

OLD_WALLPAPER="$(desktoppr)"
WALLPAPER_DIR=~/.Wallpaper
WALLPAPER_SWITCH=30m

[[ -d $WALLPAPER_DIR ]] || mkdir $WALLPAPER_DIR

cleanup()
{
desktoppr $OLD_WALLPAPER
exit 0
}

download()
{
local IMAGE=$1
while true
do
wget https://t.alcy.cc/ycy -O "$IMAGE"

for file in "$WALLPAPER_DIR"/*; do
[ "$file" = "$IMAGE" ] && continue
if cmp -s "$IMAGE" "$file"; then
DUPLICATE="$file"
break
fi
done

[ -z "$DUPLICATE" ] && break
rm -f "$IMAGE"
done
}

trap cleanup INT

while true
do
IMAGE="$WALLPAPER_DIR/$(date +"%Y-%m-%d-%H-%M-%S").webp"
download $IMAGE
desktoppr $IMAGE
sleep $WALLPAPER_SWITCH
done

事实上,在测试过程中我发现了一个有意思的细节:如果每次下载的壁纸文件名都是固定的,那么即便图片内容发生了变化,macOS 也不会触发壁纸更新——系统内部似乎存在一套基于文件名的比对机制,原本可能是为了优化性能、避免重复加载同一张图片而设计的。但这也意味着如果我要实现真正的轮换,就必须确保每次下载的文件名都不一样。所以我最终采用了 date +"%Y-%m-%d-%H-%M-%S" 的时间戳格式来命名,既保证了唯一性,又方便日后回溯查看某张壁纸是什么时候换上的。脚本还会在启动时备份老壁纸,这样即使中途被中断或者出现意外,也能优雅地恢复原状——毕竟没人希望退出脚本后桌面突然变黑或者卡在最后一张图片上。

为了提升健壮性,我还针对 Ctrl + C 做了专门处理,确保信号触发时能先恢复旧壁纸再安全退出,不会留下任何遗留问题。原先我考虑过用递增数字来命名文件,但后来想想还是时间日期更加直观,一眼就能看出切换的时序,也便于后期清理旧文件。和市面上那些功能繁重的壁纸软件相比,这个脚本最大的优势在于资源占用极其微小——它只是一个轻量级的 Shell 循环,不会常驻后台进程,也不会在休眠时继续执行更换操作,既省电又省心。