gsettings 指令
Ubuntu 用了一陣子,這幾天突然想說手動換桌布好麻煩,可不可以自動更換呢?就找了一下指令,只要一行:
gsettings set org.gnome.desktop.background picture-uri file:/home/tony/Pictures/wallpaper/123.jpg
使用 gsettings
指令,後面搭配設定桌布的參數 set org.gnome.desktop.background picture-uri file:
,接上圖檔的完整(絕對)路徑。
註:這裡的 Ubuntu 是 20.04 版。
Python 程式碼
接著用 Python 寫個簡單的程式 wallpaper.py
,把我的桌布目錄裡面全部的檔案記下來,然後隨機挑一個將它設定為桌布:
import os
import random
# 桌布目錄的完整路徑
path = "/home/tony/Pictures/wallpaper/"
# 用來儲存所有圖檔的陣列
pic_url_list = []
# 把桌布目錄底下包含子目錄全跑一遍
for (root, dirs, files) in os.walk(path):
for f in files:
# 去掉"."開頭的隱藏檔,只挑選 png 及 jpg 檔
if not f.startswith(".") and (f.endswith(".png") or f.endswith(".jpg")):
pic_url_list.append(os.path.join(root, f))
# for p in pic_url_list:
# print(p)
# print(len(pic_url_list))
max_index = len(pic_url_list) - 1
random_index = random.randint(0, max_index)
wallpaper_url = pic_url_list[random_index]
# print(wallpaper_url)
cmd = "gsettings set org.gnome.desktop.background picture-uri file:"
os.system(cmd + wallpaper_url)
附圖比較好看:
直接測試看看能不能正常執行:
python3 wallpaper.py
使用 shell 來執行
如果直接在 crontab 上排程 wallpaper.py
會無法正常執行,我找了好久才找到原因,因為使用 gsettings
的關係,我們必須額外設定環境變數 DBUS_SESSION_BUS_ADDRESS
,所以必須寫一個簡單的 wallpaper.sh
:
#!/bin/bash
# 使用 gsettings 必須設定 DBUS_SESSION_BUS_ADDRESS 環境變數
PID=$(pgrep -f 'gnome-session' | head -n1)
export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-)
# 執行 wallpaper.py
/usr/bin/python3 /home/tony/Pictures/wallpaper/wallpaper.py
立即測試
sh ./wallpaper.sh
成功的話就可以來設定排程了。
設定排程 Crontab
指令:
crontab -e
會開啟預設編輯器,如果出現錯誤無法開啟,請先設定預設編輯器:
# === bash shell ===
# 編輯
vim ~/.bashrc
# 加入
export EDITOR=vim
# === fish shell ===
# 編輯
vim ~/.config/fish/config.fish
# 加入
set -gx EDITOR vim
排程內容:
# 每隔 5 分鐘換新桌布
*/5 * * * * /home/tony/Pictures/wallpaper/wallpaper.sh > /dev/null 2>&1
這樣就完成了。
Unsplash 版
後來寫了一個進階版,自動抓取 Unsplash 上的圖片做為桌布。必須先註冊 Unsplash 並且成為開發者,然後取得 ACCESS_KEY 就能呼叫 Unsplash API 了,程式碼如下:
import requests
import json
import os
import datetime
wallpaper_path = "/home/tony/Pictures/wallpaper/"
# 讀取 keyword 檔
def read_keyword():
keywords = []
with open(wallpaper_path + "keyword.txt", "r") as f:
for line in f.read().splitlines():
keywords.append(line)
return keywords
# 請求 json 內容
def request_unsplash_json(keywords = ["wallpaper"]):
query_string = "+".join(keywords)
url = "https://api.unsplash.com/photos/random?client_id=這裡放你自己的ACCESS_KEY&orientation=landscape&query=" + query_string
req_json = requests.get(url)
return req_json.text
# 解析 json 回傳圖片 id 及網址
def parse_json_get_pic_id_and_url(json_string, pref_width = "3840"):
obj = json.loads(json_string)
pic_id = obj["id"]
# print(pic_id)
# 可用的預設尺寸: raw,full,regular(w1080),small(w400),thumb(w200)
# 使用 full 可以自訂寬度
pic_url = obj["urls"]["full"]
pic_url_w = pic_url + "&w=" + pref_width
# print(pic_url)
return (pic_id, pic_url_w)
# 取得目前日期時間
def current_date_time():
return datetime.datetime.now().strftime("%Y%m%d%H%M")
# 下載圖片並儲存
def download_picture(pic_id, pic_url):
dt = current_date_time()
file_name = dt + "_" + pic_id + ".jpg"
wallpaper_url = wallpaper_path + file_name
pic = requests.get(pic_url)
with open(wallpaper_url, "wb") as f:
f.write(pic.content)
return wallpaper_url
# 設定桌布
def set_wallpaper(wallpaper_url):
cmd = "gsettings set org.gnome.desktop.background picture-uri file:"
os.system(cmd + wallpaper_url)
keywords = read_keyword()
json_string = request_unsplash_json(keywords)
(pic_id, pic_url) = parse_json_get_pic_id_and_url(json_string)
wallpaper_url = download_picture(pic_id, pic_url)
set_wallpaper(wallpaper_url)
附圖 (連結)
API 會回傳 json 格式的內容。
我指定一組 keyword 給 Unsplash API ,讓它找到的一張隨機 (random) 圖片。圖片尺寸可以依自己的螢幕選擇寬度,例如指定 regular
就會回傳寬 1080px 的圖片尺寸,如果要指定寬度可以用 full
然後給 w
參數。
圖片名稱我用「日期 + 時間 + _ + id」的方式組合,會像這樣 202205231555_gaBANnWdDc8.jpg
另外,要新增一個關鍵字檔案 keyword.txt
,內容就是一行一個關鍵字:
travel
city
car
cat
sky
architecture
改了一個防止重覆並重抓的版本
加註日期的方式雖然方便確認順序,但是 Unsplash 給的隨機圖片會重覆,所以改了一個單純只用 id 來命名的版本,並且在重覆時重新抓一個新的,總共試三次,程式碼有一半不動:
import time
# ... 略過重覆程式碼
# 產生準備儲存在本地的桌布完整路徑
def make_wallpaper_full_path(pic_id):
# dt = current_date_time()
# file_name = dt + "_" + pic_id + ".jpg"
#
file_name = pic_id + ".jpg"
return wallpaper_path + file_name
# 下載圖片並儲存
def download_picture(pic_url, wallpaper_full_path):
pic = requests.get(pic_url)
with open(wallpaper_full_path, "wb") as f:
f.write(pic.content)
# 設定桌布
def set_wallpaper(wallpaper_full_path):
cmd = "gsettings set org.gnome.desktop.background picture-uri file:"
os.system(cmd + wallpaper_full_path)
# 主程式
def main():
keywords = read_keyword()
wallpaper_full_path = ""
pic_url = ""
# 重抓次數: 3
retry = 3
while retry > 0:
json_string = request_unsplash_json(keywords)
(pic_id, pic_url) = parse_json_get_pic_id_and_url(json_string)
wallpaper_full_path = make_wallpaper_full_path(pic_id)
# 已存在就重抓
if os.path.exists(wallpaper_full_path):
wallpaper_full_path = ""
pic_url = ""
retry -= 1
print("sleep 3 seconds then retry")
time.sleep(3)
else:
break
#
if len(wallpaper_full_path) != 0:
download_picture(pic_url, wallpaper_full_path)
set_wallpaper(wallpaper_full_path)
main()
另外,每五分鐘換一次桌布下載的圖片太多了,硬碟可能沒多久就爆了,改成 20 分鐘一次。關鍵字調整到現在拿到的圖片比較喜歡:
house
city
building
road
ocean
參考資料: https://askubuntu.com/questions/742870/background-not-changing-using-gsettings-from-cron
由 Tony Blog 撰寫,請勿全文複製,轉載時請註明出處及連結,謝謝 😀
我要留言
留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。