Can I automatically change the desktop wallpaper everytime I log on

I have learned how to change the background via the terminal but can I get the terminal to change to a different background every time I log on?


Introduction

The script below takes a directory as argument ( preferably only containing images ) , selects random item form its contents, and sets the item as wallpaper. It is intended to be started on user's login, although can be used by itself just as well.

Setting up and Usage

First of all, the script must be stored somewhere on the system. Preferably, it should be placed into your ~/bin directory. If you don't have bin directory in your home directory, then just create one.

Next,ensure the script has executable permissions. You can use either chmod +x ~/bin/set_random_wallpaper.py or do it the GUI way by right clicking on the file and checking Allow executing file as program in the Permissions tab of the Properties menu.

The script requires a directory as argument. Preferably, you should give it full path. For example:

set_random_wallpaper.py /home/JohnDoe/Pictures/wallpapers/ 

If you are doing it via command-line, then you can give relative path, Pictures/wallpapers/ , but for setting it up to run upon login automatically , use full path.

To make the file run upon every login, open Startup Applications program and click "Add" button. Use full path to command and to folder:

/home/JohnDoe/bin/set_random_wallpaper.py /home/JohnDoe/Pictures/wallpapers/ 

That's it !

Script Source

The script is also available on GitHub:

#!/usr/bin/env python3
"""
Author: Serg Kolo , <[email protected]>
Date: December, 21,2016
Purpose: Sets random wallpaper from a given directory
Written for: https://askubuntu.com/q/851705/295286
"""
from gi.repository import Gio
import os,sys,random

def gsettings_set(schema, path, key, value):
    """Set value of gsettings schema"""
    if path is None:
        gsettings = Gio.Settings.new(schema)
    else:
        gsettings = Gio.Settings.new_with_path(schema, path)
    if isinstance(value, list):
        return gsettings.set_strv(key, value)
    if isinstance(value, int):
        return gsettings.set_int(key, value)
    if isinstance(value,str): 
        return gsettings.set_string(key,value)

def error_and_exit(message):
    sys.stderr.write(message + "\n")
    sys.exit(1)

def select_random_uri(dir_path):

    selection = random.choice(os.listdir(dir_path))
    selection_path = os.path.join(dir_path,selection)
    while not os.path.isfile(selection_path):
        selection = random.choice(os.listdir(dir_path))
        selection_path = os.path.join(dir_path,selection)

    selection_uri = Gio.File.new_for_path(selection_path).get_uri()
    return selection_uri

def main():
    """ Program entry point"""
    if len(sys.argv) != 2:
       error_and_exit('>>> Script requires path to a directory as single argument')
    if not os.path.isdir(sys.argv[1]):
       error_and_exit('>>> Argument is not a directory')   
    img_dir = os.path.abspath(sys.argv[1])
    uri = select_random_uri(img_dir)
    try:
        gsettings_set('org.gnome.desktop.background',None,'picture-uri',uri)
    except Exception as ex:
       error_and_exit(ex.repr()) 

if __name__ == '__main__': main()

Technical details and theory of operation

The script itself works in pretty simple way, but I spiced it up with a few functions of my own. The main function checks if there is an argument and if that argument is a directory - otherwise it quits. If everything is OK, we proceed to get absolute path of the directory, and give it to set_random_uri() function.

As you may or may not know, the wallpaper is set in dconf database, which can be accessed and altered with gsettings command. The simple command line way is

gsettings set org.gnome.desktop.background picture-uri file:///home/JohnDoe/Pictures/cool_wallpaper.jpg

The file://... part is the file's URI (which is essentially a encoded path of the file, and is quite useful if your system uses different locale than English). First, we need to select random file and get its URI. That's simple - we use random.choice() to select from list and os.listdir() to get list of items in directory. What if our random selection happens to be a directory and not a file ? Well, that's what while loop is for in select_random_uri. Once we're happy with the selection, we get its

Well, from there that is pretty much the same thing that is happening in gsettings set command, but I'm using custom-written gsettings_set() function, avoiding the need to call an external command, and it has been useful for other projects, such as Launcher List Indicator.

That's it ! Have fun coding and enjoy Ubuntu responsibly !

Additional resource

  • Bash version of such script has been implemented before, see: https://askubuntu.com/a/744470/295286