web-dev-qa-db-ja.com

季節ごとに動的な壁紙ディレクトリを変更する

壁紙を季節(夏、秋、冬、春)にしたいが、季節をテーマにした壁紙で毎日更新したい。

本質的に、4つのディレクトリ(summer, fall, winter, spring)を持つことを考えています。夏の間、私の壁紙の背景は、毎日summerディレクトリ内の画像を回転します。その後、9月21日に壁紙ディレクトリがfallに変更され、壁紙はこれらの画像を毎日循環します。

スクリプトを作成するのは問題ありませんが、どこから始めますか?

この質問のユニークさ

編集:この質問をユニークにするものをさらに明確にする。スライドショーを作成する方法は多数ありますが、それらはすべて画像ディレクトリの設定に依存しています。私が求めているのは、画像ディレクトリを動的に変更する方法です。したがって、今日のスライドショーは/images/winter/ディレクトリから出てきて、春のスライドショーは/images/spring/ディレクトリから出てきます。季節ごとに外観設定のディレクトリを変更するだけで、手動でこれを行うことができますが、コンピューターに指示を出すことができる場合は、そのようにしたくありません。

5
Joseph Gilgen

基本的な質問は、春、夏、秋、冬の初めに何かをする方法です。このために、エントリでcronを詰まらせるのではなく、ブート時に実行されるbashスクリプトを作成します。

OPの質問「スクリプトを開発するにはどうすればよいですか?」を使用して、この回答にアプローチしました。だから私は、bashスクリプトを単に投稿する通常の方法から外れ、答えを次のように拡張しました。

  • 参照はコード内に含まれています。特定の問題を解決するためのStack Exchangeの回答にリンクしています。例:ファイルをコピーする方法、年の日付を取得する方法など。
  • 「テスト」に関するセクションは、私たち全員が行う必要があるものとして提供されています
  • ソフトウェアは通常、以前のバージョンよりも段階的に改善されたバージョンで開発されるため、「拡張機能」に関するセクションが提供されています。

季節はいつ始まりますか?

農夫の年鑑 から:

2018年の季節

 Season     Astronomical Start                     Meteorological Start
 ======     =====================================  =====================
 SPRING     Tuesday, March 20, 12:15 P.M. EDT      Thursday, March 1 
 SUMMER     Thursday, June 21, 6:07 A.M. EDT       Friday, June 1
 FALL       Saturday, September 22, 9:54 P.M. EDT  Saturday, September 1
 WINTER     Friday, December 21, 5:23 P.M. EST     Saturday, December 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+Alt+T

ディレクトリが存在しない場合は作成します: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.shBEFORE BEFOREを使用すると、スライドショープログラムが最初に起動した場合にクラッシュするファイルを削除およびコピーするため、通常のスライドショーを使用できます。


テスト中

作成時にseason.shスクリプトをテストし、正常に動作するかどうかを確認するのに1年待たないようにする必要があります。参照: https://serverfault.com/questions/138325/faking-the-date-for-a-specific-Shell-session


機能強化

最初にスクリプトを開発した後、数日、数週間、数ヶ月、さらには数年後にそれを強化するのが一般的です。このセクションでは、今後session.shに対して行う可能性のある拡張機能について説明します。

ファイルを圧縮してディスク容量を節約する

オフシーズンイメージをTAR(テープアーカイブ)形式で圧縮して、ディスク領域を節約することを検討してください。次に、cp(コピー)コマンドをtarコマンドに置き換えて、ファイルを圧縮解除します。リファレンス: https://www.rootusers.com/23-tar-command-examples-for-linux/

たとえば、次のように変更します。

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

に:

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

...その他の季節についても同様です。

シーズン開始のセットアップ変数

シーズン開始日の変数を使用すると、スクリプトの変更が容易になり、コードが読みやすくなります(別名code readability)。

シーズンの始まりに変数を設定することを検討してください。

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

注:私はこの答えを1時間で終えることを望んでいましたが、それは2時間であり、土曜日の買い物をしなければなりません。つづく...

1

おそらくこれは簡単な方法です:

  1. ~/images/mybackgroundsから~/images/springへのシンボリックリンクを作成します。

    ln -s ~/images/spring ~/images/mybackgrounds
    
  2. これらの方法の1つ を使用して~/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エントリーは同じトリックを引き出します。

2
unutbu

ステップ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.pyは、季節に応じて、~/images/spring~/images/summer~/images/fall、または~/images/winterの4つのディレクトリのいずれかで画像を検索することに注意してください。

ステップ3:crontabを構成する

cron を使用すると、コマンドを定期的に実行して、バックグラウンドを変更できます。たとえば、1日1回または1分ごとに1回です。

たとえば~/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に登録します。

これで、背景が1分ごとに変化することがわかります。 (このようにしておくのも楽しいかもしれません。)

crontabは、#で始まる行を無視します。したがって、背景を1日に1回変更する場合は、2行目をコメント解除し、3行目をコメントアウトして、~/mycrontabが次のようになるようにします。

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

ただし、その日の午前9時にマシンにログインしている場合にのみ、cronはこのコマンドを実行します。

0
unutbu
  1. homeディレクトリ~/SeasonalWallPapersにSeasonalWallPapersフォルダーを作成します
  2. ~/SeasonalWallPapers秋、春、夏、冬にサブフォルダーを作成します。
    • スクリプトは.jpgファイルを取得するためにのみ変更されるため、上記の4つのフォルダーには.jpgファイルのみを保持します

enter image description here

  • 以下の画像の.xmlファイルはスクリプトによって生成されることに注意してください。あなたはそれを作成/心配する必要はありません。

enter image description here

enter image description here

enter image description here

enter image description here

  1. 上記の4つのフォルダーのそれぞれに、以下のコンテンツを持つ4つのスクリプトを作成します。
    FWP.shRWP.shSWP.shWWP.sh

注:他の3つのスクリプトファイルの以下のスクリプトFILE="FWP.xml"の3行目を変更して、FILE=RWP.xmlFILE=SWP.xmlおよびFILE=WWP.xmlにします。

注:以下のスクリプトでは、期間は2秒のみに設定されています。実際には、壁紙の毎日の変更について、86400に設定します

#!/bin/bash

FILE="FWP.xml"
DURATION=2.0
TRANSITION=0.0

CURRENTDIR=$PWD
TRANSITION_XML="
<static>
    <duration>$DURATION</duration>
    <file>$CURRENTDIR/%s</file>
</static>
<transition>
    <duration>$TRANSITION</duration>
    <from>$CURRENTDIR/%s</from>
    <to>$CURRENTDIR/%s</to>
</transition>
"

# Random order
IMGS=( *.jpg )
INDICES=( $(shuf -e ${!IMGS[@]}) ) # randomize indices of images
INDICES+=(${INDICES[0]})           # go back to first image after last
COUNTER=${#IMGS[@]}

exec > "$FILE"                     # all further output to the XML file
echo "<background><starttime></starttime>"

for ((i = 0; i < COUNTER; i++))
do
    index=${INDICES[i]}
    printf "$TRANSITION_XML" "${IMGS[index]}" "${IMGS[index]}" "${IMGS[index + 1]}"
done

echo "</background>"
  1. scripsを実行可能にします

chmod +x ~/SeasonalWallPapers/Fall/FWP.sh
chmod +x ~/SeasonalWallPapers/Spring/RWP.sh
chmod +x ~/SeasonalWallPapers/Summer/SWP.sh
chmod +x ~/SeasonalWallPapers/Winter/WWP.sh

  1. 以下の内容でWP.shというスクリプトを作成します。
#! /bin/bash

cd ~/SeasonalWallPapers/Summer/ && ./SWP.sh
cd ~/SeasonalWallPapers/Fall/ && ./FWP.sh
cd ~/SeasonalWallPapers/Winter && ./WWP.sh
cd ~/SeasonalWallPapers/Spring && ./RWP.sh
  1. WP.shでスクリプトchmod +x ~/SeasonalWallPapers/WP.shを実行可能にします

*このスクリプトWP.shは、今後の主な情報源です。
画像のこれら4つのフォルダーの変更を追加または削除するときは、このスクリプトを実行して.xmlファイルを更新する必要があります

  1. コマンドを実行して、必要な.xml filesを生成します
    ~/SeasonalWallPapers/WP.sh

例:

$ ~/SeasonalWallPapers/WP.sh
$ 

*このスクリプトWP.shを実行すると、.xmlFWP.xmlRWP.xmlおよびSWP.xmlという名前の更新された壁紙を含む各フォルダーにWWP.xmlファイルが生成されます。

必要に応じて、これら4つの.xmlファイルのいずれかを設定する必要があります。

  1. gsettings set org.gnome.desktop.background picture-uri 'file:///home/user-name/SeasonalWallPapers/Fall/FWP.xml'#ユーザー名を自分のものに変更します。

例:

$ gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Fall/FWP.xml'
$ 

いつでも好きなときに、以下のコマンドで必要な壁紙を設定できます

gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Fall/FWP.xml'

gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Winter/WWP.xml'

gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Spring/RWP.xml'

gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Summer/SWP.xml'

enter image description here

enter image description here

enter image description here

enter image description here

3か月ごとに来る自動化をまだ考えている場合。
次のコマンド例を使用して、必要に応じてcronジョブを作成します。

0 0 1 12 * root gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Fall/FWP.xml'
0 0 1 6 * root gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Winter/WWP.xml'
0 0 1 9 * root gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Spring/RWP.xml'
0 0 1 3 * root gsettings set org.gnome.desktop.background picture-uri 'file:///home/pratap/SeasonalWallPapers/Summer/SWP.xml'
0
PRATAP