Linux Customization: Going beyond Themes and Icon Packs with Shell Scripting

CT Solutions
Geek Culture
Published in
8 min readJun 11, 2021

Who is this article for?

Bored beginner-intermediate Linux users wanting to make their machines more fun to use.

Any prerequisites?

None in particular, but basic knowledge of programming concepts such as if conditions and loops would be great.

In this article, we’re going to take a different look at Linux customization. If you use Linux as your primary OS or just installed it for work, once in a while, you must have tinkered with different themes and icon packs to give your system as personalized a feel as possible. And when you’re done, the question arises —

what’s next? Can I take it to another level? Perhaps my system could greet me, or it could change its shades depending upon the time or maybe something else?

The answer is yes. Yes, you can take your Linux customization to another level and transcend your daily desk experience to something as personalized as it can get. Possibilities are endless, of course. And as we move further into this article, we’ll try to explore some of those possibilities.

We won’t be expanding this article’s length unnecessarily trying to explain things like what Linux is or how a Linux distribution works, assuming you guys already know it. But in case you’re a beginner and want to understand things better, you can refer to our article A Perfect Linux Distribution. So without further ado, let’s dive right into it.

What is Shell and Shell Scripting

To put it simply, a shell is an interface provided to us users to help us interact with the OS. It acts as a layer between the user and the kernel, taking the high-level commands from the end-user and providing them to the kernel in the form it understands them. Normally, a shell is accessible to us users via command-line interfaces such as terminal and command prompt.

A shell script is a text file consisting of a bunch of commands to be executed/interpreted directly or based on some logic. Normally, a shell script file has a ‘.sh’ extension.

Some use-cases of shell scripting:

  • To avoid repetitive tasks
  • Automation
  • Manipulating files
  • System monitoring, etc

But these are not limited to work. Some fun cases that we’ve used shell scripting for:

  • Audio greeting on login.
  • Detecting internet connection’s status to switch wallpapers and play sounds.
  • Detecting battery’s status (full, charging, discharging). What for? You may ask. Switching wallpapers, of course. This one looks quite appealing if the right pictures are used. And this is exactly what we’re going to do in the next section.

Fun Scripting

Whenever you’re writing a script like this, you need to figure out two things first.

  • Source: By this, We’re referring to the data upon whose values our script will act.
  • Action: By this, We’re referring to the things we wish to perform based on the values obtained from our source.

Obtaining the source part for our script is quite simple, with a small google search, once you’ve figured out what exactly you need. In this script, our source will be values related to our battery’s status. Upon little tinkering, I found two ways to do this.

  1. upower -i /org/freedesktop/UPower/devices/battery_BAT1

2. cat /sys/class/power_supply/BAT1/status

We’ll use the first one since it gives us a lot more information and keeps the window for scalability open.

Now the question is, how do we retrieve that exact information we need from the pool of information we obtained using “upower”. The answer is “grep”. The grep command is used to filter out the searches based on a particular pattern of characters. We’ll need the pipe command to do this correctly. Now, what pipe command does is, it will let us use the output of one command as input of another and it looks like ‘|’.

So, now our source command will look like this:

upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E “state”

(Note: On some devices, it might be battery_BAT0)

But it’s still not in a usable state. We’ll make use of xargs, which is also useful for removing unnecessary blank spaces from strings and cut, which allows us to cut a line in the desired manner.

After applying these, our source command will become something like this:

upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E “state” | xargs | cut -d’ ‘ -f2

Where arguments -d’ ‘ is telling it to cut the line at space and -f2 is telling it to pick up the second part of the line.

Now that we have our source ready, we need to think about the action. This will depend upon what desktop environment you’re using. On something like i3wm, feh will work great. In our case, We have used xfce4, so you’ll have to first run this command to check what properties get changed upon changing wallpaper:
xfconf-query -c xfce4-desktop -m

Upon running the command, it’ll enter the monitoring mode. Change the wallpaper using the GUI method to see the properties here.

So our final action command will look like this:

xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitoreDP-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/wallpaper.jpg

Now that we’ve gathered our ingredients, it’s time to make the actual dish. First, we’ll store our source’s output somewhere. Let’s store it in a variable named ‘battery’:

#!/bin/bash
battery=$(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "state"|xargs|cut -d' ' -f2|sed s/%//)

The expression $() is command substitution here.

Notice we used “#!/bin/bash” at the start of our script, it is called “shebang”. Its purpose is to tell the OS to invoke the specified shell to execute our commands.

Now we’ll make use of if-elif-else structure, to place our actions:

#!/bin/bash
battery=$(upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E "state" | xargs | cut -d' ' -f2)
if [ "$battery" = "charging" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png)
echo "Charging case hit!"
elif [ "$battery" = "discharging" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok0.png)
echo "Discharging case hit!"
elif [ "$battery" = "fully-charged" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png)
echo "Fully-charged case hit!"
else
echo "Something went wrong!"
fi

Now, our script should be working. Don’t forget to make it an executable with chmod +x filename.sh and then run it like this ./filename.sh. The output should look something like this:

But this is just a one-time thing. To make it keep running in the background, we’ll make use of loops. In this case, We’ll be using a while loop. So, let’s add a while loop to our script.

#!/bin/bash
while true
do
battery=$(upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E "state" | xargs | cut -d' ' -f2)
if [ "$battery" = "charging" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png)
echo "Charging case hit!"
elif [ "$battery" = "discharging" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok0.png)
echo "Discharging case hit!"
elif [ "$battery" = "fully-charged" ]; then
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png)
echo "Fully-charged case hit!"
else
echo "Something went wrong!"
fi sleep 5
done
done

Notice that we’ve added “sleep” command at the end of the loop, so our script isn’t executing the command like a maniac. Now everything looks and works great or does it? In case you’ve not noticed, we’re changing wallpaper every 5 seconds. Since we’re the same case most of the time, it goes unnoticed. Let’s fix this!

After adding a helper variable and nested ifs, our final script looks like this:

#!/bin/bash
while true
do
battery=$(upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E "state" | xargs | cut -d' ' -f2)
if [ status = "" ]; then
status="none"
fi
if [ "$battery" = "charging" ]; then
if [ "$status" != "charging" ]; then
status="charging"
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png
)
echo "Charging case hit!"
fi
elif [ "$battery" = "discharging" ]; then
if [ "$status" != "discharging" ]; then
status="discharging"
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok0.png
)
echo "Discharging case hit!"
fi
elif [ "$battery" = "fully-charged" ]; then
if [ "$status" != "fully-charged" ]; then
status="fully-charged"
$(xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitorHDMI-1/workspace0/last-image -s /home/wolfian/Pictures/Wallpapers/ragnarok1.png
)
echo "Fully-charged case hit!"
fi
else
echo "Something went wrong!"
fi
sleep 5
done

As we have mentioned earlier, how appealing the result is, mostly depends upon the wallpapers you choose. Our end result looks like this,

Discharging:

Charging:

(Note: Don’t forget to add the script to run on startup.)

That’ll be all for this article. Have fun! Also, if you’ve anything to add to this topic or want anything Linux-related in particular for us to cover, let us know in the comments below.

--

--

CT Solutions
Geek Culture

Driven by the zeal to bring in a change in the digital world, Catalyst Technology Solutions will evolve your brand globally.