介绍

介绍

我希望我的壁纸具有季节特色(夏季、秋季、冬季、春季),而且每天更新季节主题壁纸。

因此,本质上,我打算有 4 个目录( )。在夏季,我的壁纸背景会每天summer, fall, winter, spring轮换目录中的图像。然后在 9 月 21 日,壁纸目录将更改为,然后壁纸将每天循环显示这些图像,依此类推。summerfall

我很乐意编写脚本,但是我该从哪里开始呢?

这个问题有何独特之处

编辑:进一步澄清是什么使这个问题变得独特。虽然创建幻灯片的方法有很多,但它们都依赖于设置图像目录。我问的是如何动态更改图像目录。因此,今天的幻灯片放映来自目录/images/winter/,春季的幻灯片放映来自目录/images/spring/。我可以通过在每个季节更改外观设置中的目录来手动执行此操作,但当我可以让计算机为我执行此操作时,我不想这样做。

答案1

介绍

基本问题是如何在春季、夏季、秋季和冬季开始时做某事。为此,我将创建一个在启动时运行的 bash 脚本,而不是用cron条目堵塞。

我使用 OP 的问题“如何开发脚本?”来回答这个问题。因此,我偏离了通常的简单发布 bash 脚本的方法,而是通过以下方式增强了答案:

  • 代码中包含参考资料。它们链接到 Stack Exchange 解答以解决特定问题。例如:如何复制文件、如何获取一年中的某一天等。
  • 提供了“测试”部分,因为这是我们每个人都需要做的事情
  • 之所以提供“增强功能”部分,是因为软件通常以新版本进行开发,每个版本都比前一个版本有所改进。

季节什么时候开始?

来自农民年鉴

2018 年的季节

季节 天文起点 气象开始
春天 3 月 20 日星期二下午 12:15(美国东部时间) 3 月 1 日,星期四
夏天 6 月 21 日星期四,上午 6:07(美国东部夏令时间) 6 月 1 日,星期五
落下 9 月 22 日星期六,晚上 9:54(美国东部夏令时间) 9 月 1 日,星期六
冬天 星期五,12 月 21 日,下午 5:23(美国东部时间) 12 月 1 日,星期六

将季节开始日期转换为一年中的某一天

为了使我们的bash脚本正常工作,我们需要知道每个季节从哪一天开始。

$ echo $(date --date="March 20" '+%j')
079
$ echo $(date --date="June 21" '+%j')
172
$ echo $(date --date="Sep 22" '+%j')
265
$ echo $(date --date="Dec 21" '+%j')
355
# Reference: https://unix.stackexchange.com/questions/352176/take-input-arguments-and-pass-them-to-date

创建 bash 脚本:season.sh

使用以下方法打开终端:Ctrl++AltT

如果目录不存在则创建该目录:mkdir -p ~/bin

使用以下方法编辑脚本:gedit ~/bin/season.sh

  • 笔记:Lubuntu 用户需要leafpad使用gedit

将以下行复制并粘贴到gedit

#!/bin/bash
# NAME: season.sh
# PATH: ~/bin
# DATE: December 15, 2018

# NOTE: Written for: https://askubuntu.com/questions/1100934/change-dynamic-wallpaper-directory-every-season/1102084#1102084

# User defined variables, change to suit your needs
# Our directory names, lines indented for cosmetic reasons only
SlideShowDir="~/Season Slide Show"
   SpringDir="~/Pictures/Spring Slide Show"
   SummerDir="~/Pictures/Summer Slide Show"
     FallDir="~/Pictures/Fall Slide Show"
   WinterDir="~/Pictures/Winter Slide Show"

CheckTripWire () {
    # Our last season is in "~/Season Slide Show/CurrentSeason"
    LastSeasonFilename="$SlideShowDir"/CurrentSeason
    LastSeason=$(cat "$LastSeasonFilename")
    
    [[ "$LastSeason" == "$Season" ]] && return 0 # Season still the same
    
    # We now know our season has changed.
    
    rm -f "$SlideShowDir"/{*,.*}           # Erase all files in target
    # Reference: https://askubuntu.com/questions/60228/how-to-remove-all-files-from-a-directory
    
    echo "$Season" > "$LastSeasonFilename" # Record new season in target
    
    # Copy new slide show based on season
    if (( "$Season" == SPRING)) ; then
        cp -R "$SpringDir"/. "$SlideShowDir"/
        # Reference: https://stackoverflow.com/questions/3643848/copy-files-from-one-directory-into-an-existing-directory
    elif (( "$Season" == SUMMER)) ; then
        cp -R "$SummerDir"/. "$SlideShowDir"/
    elif (( "$Season" == FALL)) ; then
        cp -R "$FallDir"/. "$SlideShowDir"/
    else
        cp -R "$WinterDir"/. "$SlideShowDir"/
    fi

} # End of CheckTripWire () function.

# Start of Mainline

DOY=$(date '+%j')                     # DOY = Current Day of Year
# Reference: https://stackoverflow.com/questions/10112453/how-to-get-day-of-the-year-in-shell

if ((DOY>=079 && DOY<172)) ; then
    Season="SPRING"                   # Spring has sprung!
    # Reference: https://stackoverflow.com/questions/12614011/using-case-for-a-range-of-numbers-in-bash
elif ((DOY>=172 && DOY<265)) ; then
    Season="SUMMER"                   # Hit the beach!
elif ((DOY>=265 && DOY<355)) ; then
    Season="FALL"                     # Rake those leaves!
else
    Season="WINTER"                   # Shovel the snow!
fi

# Current season establish, now see if we tripped the wire
CheckTripWire

exit 0 # Command not necessary but good habit to signify no Abend.

将文件保存在 中gedit。现在使用以下命令将其标记为可执行文件:

chmod a+x ~/bin/season.sh

接下来我们需要将其添加到启动应用程序中。参考:如何在登录时自动启动应用程序?

笔记:您可能已经在启动应用程序中设置了幻灯片放映。您将需要使用season.sh 您的常规幻灯片放映,因为它会删除并复制文件,如果幻灯片放映程序首先启动,这会导致幻灯片放映程序崩溃。


测试

您将希望season.sh在创建脚本时对其进行测试,而不是等待一年来查看它是否正常运行。参考:伪造特定 shell 会话的日期


增强功能

最初开发脚本后,通常会在几天、几周、几个月甚至几年后对其进行改进。本节讨论您可能希望在session.sh以后进行的一些改进。

压缩文件以节省磁盘空间

考虑将淡季图像压缩为柏油(磁带存档)格式以节省磁盘空间。然后用解压文件的命令替换cp(复制)命令。参考:tar23 个 Linux 的 tar 命令示例

例如,我们将改变:

cp -R "$SpringDir"/. "$SlideShowDir"/

到:

tar -xf "$SpringDir"archive.tar -C "$SlideShowDir"/

...其他季节也是如此。

设置赛季开始的变量

使用变量表示赛季开始日期可以更轻松地修改脚本,并使代码更易于阅读(又名代码可读性)。

考虑设置赛季开始的变量:

SpringStart=079
SummerStart=179
FallStart=265
WinterStart=355

在脚本顶部定义变量,使它们更容易发现和更改。您可能希望对闰年这样做。您可能希望将季节开始日期更改为“气象”日期,而不是“天文”日期。

然后更改以下几行:

if ((DOY>=079 && DOY<172)) ; then
elif ((DOY>=172 && DOY<265)) ; then
elif ((DOY>=265 && DOY<355)) ; then

对此:

if ((DOY>="$SpringStart" && DOY<"$SummerStart")) ; then
elif ((DOY>="$SummerStart" && DOY<"$FallStart")) ; then
elif ((DOY>="$FallStart" && DOY<"$WinterStart")) ; then

答案2

也许这是一个更简单的方法:

  1. ~/images/mybackgrounds创建从到 的符号链接~/images/spring

    ln -s ~/images/spring ~/images/mybackgrounds
    
  2. 使用这些方法之一显示使用来自的图像的背景幻灯片~/images/mybackgrounds

  3. 设置 crontab 条目以在特定日期更改符号链接。创建一个名为的文件,~/mycrontab其内容如下:

    # min  hr     day     mon  dow
    0      9      21      3    *     ln -sf ~/images/spring ~/images/mybackgrounds
    0      9      21      6    *     ln -sf ~/images/summer ~/images/mybackgrounds
    0      9      21      9    *     ln -sf ~/images/fall ~/images/mybackgrounds
    0      9      21      12   *     ln -sf ~/images/winter ~/images/mybackgrounds
    

    跑步

    crontab ~/mycrontab
    

    注册 crontab 条目。3 月 21 日上午 9 点,crond将运行以下命令

    ln -sf ~/images/spring ~/images/mybackgrounds
    

因此链接~/images/mybackgrounds~/images/spring。6 月 21 日上午 9 点, crond将更改符号链接,使~/images/mybackgrounds指向 ~/images/summer。幻灯片程序配置为从 中选择一个文件 ~/images/mybackgrounds。 到 的路径~/images/mybackgrounds保持不变,但现在所有内容都不同,因为符号链接指向不同的位置。9 月 21 日和 12 月 21 日的 crontab 条目使用了同样的技巧。

答案3

步骤 1:创建 slideshow.py 脚本

~/bin/slideshow.py将其保存在名为:的文件中。

#!/usr/bin/env python
import os
import datetime as DT
import itertools as IT
import bisect
import random
import subprocess

# customize cutoffs and image_dirs however you like, but note that there must be
# the same number of items in each, and the items in cutoffs must be in sorted order.
cutoffs = [(3, 21), (6, 21), (9, 21), (12, 21)]
image_dirs = ['~/images/winter', '~/images/spring', '~/images/summer', '~/images/fall']
image_dirs = list(map(os.path.expanduser, image_dirs))

today = DT.date.today()
year = today.year

# convert the cutoffs to actual dates
cutoff_dates = [DT.date(year, m, d) for m, d in cutoffs]
# find the index into cutoff_dates where today would fit and still keep the list sorted
idx = bisect.bisect(cutoff_dates, today)
# use idx to get the corresponding image directory 
image_dir = next(IT.islice(IT.cycle(image_dirs), idx, idx+1))

# list all the files in image_dir (even in subdirectories, and following symlinks)
files = [os.path.join(root, filename)
         for root, dirs, files in os.walk(image_dirs[idx], followlinks=True)
         for filename in files]
# pick a file at random
imagefile = os.path.abspath(random.choice(files))

# find the current process's effective user id (EUID)
euid = str(os.geteuid())
# find the pid of the current EUID's gnome-session
pid = subprocess.check_output(['pgrep', '--euid', euid, 'gnome-session']).strip().decode()
# load all the environment variables of gnome-session
env = open('/proc/{}/environ'.format(pid), 'rb').read().strip(b'\x00')
env = dict([item.split(b'=', 1) for item in env.split(b'\x00')])
# get the value of DBUS_SESSION_BUS_ADDRESS environment variable
key = b'DBUS_SESSION_BUS_ADDRESS'
env = {key: env[key]}
# call gsettings to change the background to display the selected file
# with the DBUS_SESSION_BUS_ADDRESS environment variable set appropriately
subprocess.call(['gsettings', 'set', 'org.gnome.desktop.background', 'picture-uri',
                 'file://{}'.format(imagefile)], env=env)

第 2 步:使其可执行:

chmod 755 ~/bin/slideshow.py

要测试一切是否按预期运行,您可以打开终端并 slideshow.py重复运行。您应该会看到背景发生变化。请注意, 根据季节的不同,在、 、或slideshow.py4 个目录之一中查找图像。~/images/spring~/images/summer~/images/fall~/images/winter

步骤3:配置crontab

您可以使用计划任务定期运行命令来更改背景,例如每天一次或每分钟一次。

创建一个名为的文件~/mycrontab,并在里面放入如下内容:

# min  hr     day     mon  dow
# 0      9      *       *    *    ~/bin/slideshow.py   # run once at 9AM
*      *      *       *    *    ~/bin/slideshow.py   # run once every minute

然后运行

crontab ~/mycrontab

将更改注册到你的 crontab。

现在您应该看到背景每分钟变化一次。(您甚至可能喜欢保持这种状态。)

crontab将忽略以 开头的行#。因此,如果您希望背景每天更改一次,请取消注释第二行并注释掉第三行,这样~/mycrontab现在看起来就像这样:

# min  hr     day     mon  dow
0      9      *       *    *    ~/bin/slideshow.py   # run once at 9AM
# *      *      *       *    *    ~/bin/slideshow.py   # run once every minute

但请注意,仅当您当天上午 9 点登录机器时,cron 才会运行此命令。

答案4

好的。以下是我对 Ubuntu 18+ 用户的看法(不确定以前的版本,因此这是一个免责声明)。

在 Ubuntu 中,可以创建一个自定义 XML 文件,其中包含指向图像的路径、“持续时间”和开始时间部分。例如:

<background>
  <starttime>
    <year>2000</year>
    <month>3</month>
    <day>21</day>
    <hour>00</hour>
    <minute>00</minute>
    <second>00</second>
  </starttime>
<static>
  <duration>30.00</duration>
  <file>/home/martin/Pictures/Slideshow/spring.jpg</file>
</static>
<static>
  <duration>30.00</duration>
  <file>/home/martin/Pictures/Slideshow/summer.jpg</file>
</static>
</background>

在此示例中,时间duration为 30 秒,开始日期/时间是 2000 年 3 月 21 日。只需添加更多具有正确持续时间的图片... 因此计算从 3 月 21 日到 6 月 21 日的秒数,并将此数字放在第一<duration>部分。然后对 6 月 21 日到 9 月 21 日执行相同操作,并将其放在第二部分。秋季和冬季也是如此。

相关内容