Bash-script your wallpapers today!

Bash-script your wallpapers today!

I have learned a lot about Arch and Linux over the last few weeks and today I decided to go ahead with bash-scripting, I had been hesitant since it seemed really hard and I had no previous knowledge about scripting. Therefore, I started watching a 20-part video on YouTube to get an idea of what I was getting in to. It might be a little slow, but it’s one of the better playlists out there – yeah I saw a lot of videos. At the same time I had been battling with codeacademys python course. I like codeacademy but it’s really hard where there is no room to wiggle. Everything has to be exactly as they say, which is almost impossible to work with. Therefore I decided to start working on my own stuff. Maybe that would be easier?

So first of all, I needed an idea of what I wanted my script to do, and not long ago I saw a time lapsed video of a guy who was writing and sometimes he stopped and changed his wallpaper. I thought this would be a good place to start. It should be pretty easy to automate that with a small script. Changing the wallpaper, not the writing.

So what I wanted was a bash script which:
1. Looks at a directory with all my wallpapers
2. Chooses a random file
3. Sets it as background
4. Does this every 15 minutes

The best thing, for me at least, is that bash-scripting is just like the commands from the terminal mixed with some other “magic” stuff. This makes it way more easy for me to learn. This all seemed really easy. I know how to go to a dir, I know the command for setting the wallpaper, and I knew that systemd had a timer and if that failed there would always be cron. Perfect.

Well.. I wasn’t wrong but.. stackoverflow quickly became a point of reference. I had several ideas of how to do this but I ended up with something completely different. Hopefully this will get easier with time. Let’s start by breaking down, what I wanted to do.

Since this is bash-scripting, we need to state that in the top of our script.

Now, I wanted the script to look in my home directory where I save my wallpapers. In my case they are located in:

The easiest way to tell the script what is going on is to make a variable “DIR”

Naturally I wanted this script to work on my own computer but I also wanted the script to work for others. You know, If I wanted to show of my new skillz.Therefore, I needed a typical variable for the user ($USER). Not a problem. This is going to be great!

Now the script knows that DIR refers to this exact directory. Great. Now we need to tell the script that it needs to randomly select a file and store it in a variable. Again pretty easy. After 2 seconds of googling I found out “ls” had a randomization command – look at the manpage. Almost too easy. Kinda.
PIC=$(ls $DIR/* | shuf -n 1)

As you can see the “PIC” is our new variable and it is defined to run a “ls” in that dir, which we defined in the earlier line. Moreover, we use the command “shuf -n 1” which means that the “ls” command also shuffles all the files and chooses a random. Now we need to do something with the new randomly selected file.
feh --bg-scale "file://$PIC"

Feh is the application I use to set the wallpaper in i3. We use the same command as we would if we were setting the background and then we point to the randomly selected file “file://$PIC”.
If you want to use the same application, make sure it is installed
sudo pacman -S feh

I’ll paste the script in its entirety below. Just fire up vim or nano and copy paste it if you want to use it.

PIC=$(ls $DIR/* | shuf -n 1)
feh --bg-scale "file://$PIC"

Cool. Now you have the four lines in your texteditor, then you can save your new script. That’s it. Save your new script with “.sh” as filename. I called mine Now that the file is created and named we also have to make it executable.
chmod +x

Now. Since I’ve set the path to the wallpapers to “~/Pictures/Wallpapers” you will either have to do create the same directory or change the path. Moreover, you need a lot of wallpapers in that directory, since having only two or three will render the randomization kinda useless. I downloaded like 20 wallpapers and some of them are kinda lame, so in the future I want to script to write out which wallpaper it is currently using and then I should be able to delete the current wallpaper with a hotkey – or at least move it. When you have all that taken care of, it’s time to try the new script by running this command:

This will execute the script. If everything is done correct this should work great, and a new wallpaper should pop up instantly.

But it’s not practical to have to start a script in the termial every time you want to change a wallpaper. Therefore we can setup a hotkey in i3-wm. Start by opening the config:
vim ~/.config/i3/config.

Add this bindsym to the config:
bindsym $mod+p exec /home/your-user/yourscript

Restart i3 ($mod+r) and try pressing the new hotkey ($mod+p).

But, I didn’t want to stop here. I also wanted my script to run every 15 minutes and therefore i downloaded cronie, which turned out to be either too complicated or not documented well enough. At last I decided to give Systemd a shot since is also has a service/timer similar to cronie. However, it seems that no matter what I did my script would fail because of feh with some odd error messages about a missing home-folder and that X was not running. I’m pretty sure that either I’m still too much a newb or my google-skillz failed me. Overall this too way more time than anything else. Therefore, I decided to end my bash-script-project with the hotkey in i3.

Or maybe – maybe I to accept my defeat and change the script. This was surely an option but I rather wanted to learn about systemd-timer or cronie as I know I have to learn that at some point. Sigh.. Well. Again, back too google and quickly I found the “while-function” yeah, I don’t know what it’s called. But if you don’t know either then it’s all good. All it does is that it repeats the command set. Cool. So I should just place it around my current script? Let’s try it.

while [ true ]
PIC=$(ls $DIR/* | shuf -n 1)
feh --bg-scale "file://$PIC"
sleep XXX

Yay! Noticed that xxx-ting? Well, the sleep-function tells it how many seconds it should sleep. To test it, I set it to 1, which is one second. Some of my wallpapers are 5-7mbs, so I guess my SSD wouldn’t really like that.. At all. I killed the process and started looking into what what else I could do with that number. The man-pages said that i could put a “m” for minute or “d” for days, but that didn’t work – maybe physiotherapist were never meant to be coders. However, I still wanted my 15 minutes and I knew how to make it work with seconds so 15×60=900 worked fine. So instead of xxx I had 900. But, I still need to run it in a terminal or start it with a hotkey when the computer starts. Not cool. Let’s look at the i3-config and set it to automatically start with i3.
vim ~/.config/i3/config

I don’t know where you want to put this, but you can put it anywhere really. I suggest you give the whole config a look and then decide where you want a section of applications which start with i3. I currently have a few, and with my new scripting abilities there will be more for sure. Add this line to your i3-config
exec --no-startup-id /home/your-user/bash/

As you can see, you need to replace “your-user” with your username and place your script in a directory called “bash”. This latter is just to keep things neat.

Please restart i3 and enjoy the randomization of wallpapers. Whilst writing this guide my wallpaper has changed a few times – It’s so satisfying.