[shell 脚本分享] 下载并设置 bing 壁纸(hyprland 或 sway)

#!/bin/env bash
# 下载并设置 bing 每日壁纸
# 适用于 hyperland/sway 环境
# version: 2025.10.07
# depends: [fd xidel curl wget]
# 用法:
# bing.sh
# bing.sh cc  # 仅从缓存中随机加载
# bing.sh cp  # 复制当天壁纸到缓存
set -eo pipefail

desktop=$XDG_SESSION_DESKTOP
today=$(date +%Y%m%d)
cache="$HOME/图片/"

function main {
	if [[ $1 == "cc" ]]; then
		# 从缓存中随机加载图片
		local random_wallpaper=$(fd -t f -0 . "$cache" | shuf -z -n 1 | xargs -0 readlink -f)
		echo "[x] Pick random wallpaper: ${random_wallpaper##*/}"
		apply_wallpaper "$random_wallpaper"
	elif [[ $1 == "cp" ]]; then
		# 保存当天的图片到缓存
		fd -d1 -e jpg -e jpeg "bing_${today}_" /tmp -x cp '{}' "$cache"
		echo "Copy today's wallpaper success."
	else
		# 下载并设置壁纸
		# 检测壁纸是否已使用
		[[ $desktop == "hyprland"]] && hyprctl hyprpaper listloaded | grep -q $today && exit
		get_wallpaper
		apply_wallpaper "$wallpaper"
	fi
}

function get_wallpaper {
	# 检测当天壁纸是否已下载
	wallpaper=$(fd -d 1 -1 -e jpg -e jpeg "bing_${today}_" /tmp)
	[[ $wallpaper ]] && return

	# 语言 (en-US,zh-CN...)
	lang="zh-Hans"
	# 下载4k分辨率,请设置 res=4k;4k以上分辨率的原始图片,请设置 res=raw
	#res=4k
	if [[ $res != "" ]]; then
		pic_src="https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&uhd=1&uhdwidth=3840&uhdheight=2160"
	else
		pic_src="https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1"
	fi

	echo "[x] Get today's wallpaper info..."
	pic_info=$(curl -sSL --compressed "$pic_src" -b "_tarLang=default=${lang}; imgv=lodlg=4&gts=20241223; MUIDB=14288E2B430465C831C29A6A424E64D1;")
	#pic_info=pic_info.json

	local date=$(echo $pic_info | xidel -e '$json/images[1]/startdate')
	[[ $date == "" ]] && date=$today

	base_url="https://www.bing.com"
	local link=${base_url}/$(echo $pic_info | xidel -e '$json/images[1]/url')
	[[ $res == raw ]] && link=$(grep -Eo "https://[-=?/._a-zA-Z0-9]+" <<<"$link")

	local title=$(echo $pic_info | xidel -e '$json/images[1]/title')
	local copyright=$(echo $pic_info | xidel -e '$json/images[1]/copyright')
	#keyword=$(echo $copyright | sed 's/, /-/g' | cut -d" " -f1 | grep -Eo '[^()\\/:*?"<>]+' | head -1)
	local filename="bing_${date}_${title}.jpg"
	echo "Link: "$link
	echo "Date: "$date
	echo "Title: "$title
	echo "Copyright: "$copyright
	#echo "Keyword: "$keyword
	echo "Filename: "$filename

	wallpaper=/tmp/$filename
	if [[ ! -f $wallpaper ]]; then
		echo "[x] Downloading wallpaper..."
		wget -t 5 --no-check-certificate $link -qO $wallpaper
	fi
	ls -lah $wallpaper || exit 2
}

function apply_wallpaper {
	echo "[x] Applying desktop wallpaper..."
	local wallpaper=$1
	case $desktop in
	hyprland)
		if hyprctl hyprpaper unload all; then
			hyprctl hyprpaper preload $wallpaper
			hyprctl hyprpaper wallpaper ",${wallpaper}"
		fi
		;;
	sway)
		swaymsg "output * bg ${wallpaper} stretch"
		;;
	esac
}

main "$@"

#echo "[x]Clean..."
#rm -f /tmp/bing_*.jpg

默认壁纸下载到 /tmp 里

其中,fd 和 xidel 命令是个人偏好,可以换成更通用的 find 和 jq

能把元数据 例如bing的照片说明 以及作者 放进文件名里吗

可以的,说明和作者应该是在 copyright 里

把 `local filename="bing_${date}_${title}.jpg"` 这一行改成 local filename="bing_${date}_${title}_${copyright}.jpg

如果 copyright 里有特殊字符,需要自己处理一下

@依云 代码段如何开启行号?:slightly_frowning_face:

不支持吧。