DEV Community

aagamezl
aagamezl

Posted on • Edited on

Changing the GNOME Shell login background

This is my first post on dev.to, and I want to share my experience on this topic, that although it basically looks simple, I always want a little more.

The "problem" is that I was just tired of the boring purple Ubuntu's background login screen, I REALLY was tired of it, so I asked myself, how can I change the login screen background?, and the quick answer was, no you can't change it, the long answer was, well, you can change it, but this involves dealing with the GNOME Shell CSS.

Changing your GNOME Shell login background is not complicated if you know what to change and where to make the change. The change consists of modifying the CSS file with the desired image, but in my case, I wanted to change this image every time that I restart my laptop, and I want to download the daily Bing image to use it as background.

I'm using Ubuntu 19.10, so to change the login background I need to modify the file /usr/share/gnome-shell/theme/Yaru/gnome-shell.css, if you are using another distro or Ubuntu version, please search for the correct path on internet, but my path can give you an idea of where to start looking.

Inside this CSS file, we need to modify the selector #lockDialogGroup from

#lockDialogGroup {
  background: #4f194c url(noise-texture.png);
  background-repeat: repeat; }
Enter fullscreen mode Exit fullscreen mode

to

#lockDialogGroup {
  background-image: url(file:///path/to/your/image.ext);
  background-repeat: no-repeat;
  background-size: cover;;
  background-position: center; 
}
Enter fullscreen mode Exit fullscreen mode

First at all, I tried to found an easy way to change every day the login background in an automatic way, but changing a CSS file every day is not a trivial task just with bash, and if I made a mistake, all my shell could be broken (trust me, that happened like 5 times while I was making manual tests and fortunately was not broken enough to be able to fix it).

After thinking for a few minutes, I realized that I could create a symbolic link to the daily image and change this symbolic link to point to a different image every day, and use this symbolic link in the CSS file, voilà, the first problem was resolved.

The command to create a symbolic link is the next:

ln -s ./path/to/your/real_file.ext ./path/to/your/fake_file.ext
Enter fullscreen mode Exit fullscreen mode

Let's move on to the next problem, this problem is randomly choosing a daily image, for this, I had to make some internet research because I'm not a bash wizard, but the trick actually is simple, we can use the shuf command, this command "Write a random permutation of the input lines to standard output", great, this looks like the perfect tool for the task, and what can we use as input? well, the perfect tool for this task is ls command.

ls ./the/path/to/your/backgrounds/**/*.ext | shuf -n 30 | shuf -n 1
Enter fullscreen mode Exit fullscreen mode

If you need to select different file types according to the extension, you could use something like this:

ls ./path/**/* | egrep '\.jpg$|\.jpeg$|\.png$|\.gif$' | shuf -n 30 | shuf -n 1
Enter fullscreen mode Exit fullscreen mode

If you are wondering why I use the shuf command twice, this is to achieve a higher level of randomness; first I choose 30 random items and after that, I choose 1 random item from the previous group.

Up to this point, we have almost solved the first part of the problem, we just need to run our script every time our PCs are restarted, for this I decided to use crontab with the @reboot modifier.

@reboot /path/to/your/script.sh
Enter fullscreen mode Exit fullscreen mode

Please don't forget to give your script execution privileges:

sudo chmod +x /path/to/your/script.sh
Enter fullscreen mode Exit fullscreen mode

Now we have all the necessary parts to fulfill the first task, so its time to have a complete script, in my case I put it in /etc/init.d/change-login-background.sh

#!/bin/bash

# General values for the script
SOURCE=./the/path/to/your/backgrounds
DAILY_LOGIN_BACKGROUND=daily-login-background.jpg
VIRTUAL_FILENAME=$SOURCE/$DAILY_LOGIN_BACKGROUND

# Change the extension according to your needs
filename=$(ls $SOURCE/**/*.jpg | shuf -n 30 | shuf -n 1)

# Check if the symbolic link exists, if exists, delete it
if test -f "$VIRTUAL_FILENAME"; then
  rm $VIRTUAL_FILENAME
fi

ln -s $filename $VIRTUAL_FILENAME

echo Daily login background: $filename
Enter fullscreen mode Exit fullscreen mode

Now we are automatically changing the login background every time we restart our PCs, the next step is to download the daily image from Bing. This is not a big problem with Node.js or PHP (my two main backend languages), but I wanted to solve this with bash only, so the complexity of the task was increased.

Again, I'm not a bash wizard, but I'm super stubborn, and I really wanted to solve this problem using just bash and at the same time, learn more about bash programming.

To get the daily Bing exists an endpoint that can give you the last 8 images (or just one) in XML or JSON format, but again, process XML or JSON just with bash tools is not a trivial task, I could just install some extra tools to do it, but not, I wanted to do it just with bash, so after some extra thinking and research, the chosen tool
for the task was... regular expressions.

Everybody stands back I know regular expressions

I know, I know, some people always say that when you have a problem and you solve it using regular expressions, now you have two problems, but in this case, I think it is the right tool for the problem. But how the hell can you use regular expressions in bash?, I was asking me the same, but again after some research, I found that with the sed command you can do it.

So the first step was to download the JSON file, for this CURL come to the rescue:

# Download the JSON file into a variable
json=$(curl -s $BING_IMAGES_URL)
Enter fullscreen mode Exit fullscreen mode

After having the JSON, you just have to get the necessary values:

# Get the url and name from the JSON
image_url=$(echo $json | sed -n 's|.*"url":"\([^"]*\)".*|\1|p')
image_name=$(echo $image_url | sed -n 's|.*?id=\(.*\)&rf.*|\1|p')
Enter fullscreen mode Exit fullscreen mode

And now we can download the image to our PCs using CURL again:

curl -s /path/to/your/images/folder -o /name/of/the/downloaded/image.ext
Enter fullscreen mode Exit fullscreen mode

Now let's put all the pieces together, in my case I put all the code in ./etc/init.d/download-bing-background.sh:

#!/bin/bash

# General values for the script
BING_DOMAIN="https://www.bing.com"
BING_IMAGES_URL="https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1"
DESTINATION=/path/to/your/background/directory
CURRENT_DIRECTORY=$(date +%Y)-$(date +%m)
DOWNLOAD_DIRECTORY=$DESTINATION/$CURRENT_DIRECTORY

echo Image Destination: $DOWNLOAD_DIRECTORY

# Download the JSON file into a variable
json=$(curl -s $BING_IMAGES_URL)

# Get the url and name from the JSON
image_url=$(echo $json | sed -n 's|.*"url":"\([^"]*\)".*|\1|p')
image_name=$(echo $image_url | sed -n 's|.*?id=\(.*\)&rf.*|\1|p')

echo Downloading image of the day: $image_name

# Check if the download directory exists or nor
if [ ! -d $DOWNLOAD_DIRECTORY ]; then
  mkdir $DOWNLOAD_DIRECTORY
fi

# Check if the image already exists
if [ -f $DOWNLOAD_DIRECTORY/$image_name ]; then
  echo Image already exists, skipping.
else
  curl -s $BING_DOMAIN/$image_url -o $DOWNLOAD_DIRECTORY/$image_name
fi
Enter fullscreen mode Exit fullscreen mode

Please don't forget to give your script execution privileges:

sudo chmod +x /path/to/your/script.sh
Enter fullscreen mode Exit fullscreen mode

Ok, this is all folks, I hope you enjoyed and learned how I did by solving this "problem" I had with Ubuntu.

If you have some questions, please send me a message on Twitter.

Top comments (0)