Intending to reuse the installation process of a GNOME extension, I wrote the following script:

# It installs a target gnome shell extension defined via url


cd ~/Downloads
wget $STORE_URL/$1 -O ./$ZIP
UUID=$(unzip -c $ZIP metadata.json | grep uuid | cut -d \" -f4)

if [[ ! -d $EXTENSIONS_PATH/$UUID ]]; then
    unzip -q ./$ZIP -d $EXTENSIONS_PATH/$UUID
    gnome-shell-extension-tool -e $UUID

rm $ZIP
gnome-shell --replace &

It expects to receive as argument the target extension zip name, one available from official GNOME extensions index. The zip file, after downloaded, will be unzipped in its UUID directory inside GNOME extensions' location and then enable.

Is there something else could be done to improve this installation process? Any of the executed commands could be improved or code get better readability?


1 Answer 1


First off, install Shellcheck and routinely run it on your scripts, or configure your editor to run it automatically. Now, Shellcheck is pretty rigorous and you would be forgiven for not solving all its warnings, but at the very least be aware of them.


On some systems there’s a more up to date bash installed in a different location. In general you’d want to use

#!/usr/bin/env bash

Though in the case of Bash on Linux I think yours is OK.1

Next, enable stricter error checking:

set -euo pipefail

From help set:

  • -e Exit immediately if a command exits with a non-zero status.
  • -u Treat unset variables as an error when substituting.
  • -o pipefail the return value of a pipeline is the status of the last command to exit with a non-zero status, or zero if no command exited with a non-zero status

Regarding your variables, there’s a convention to use UPPER_CASE for environment variables, and snake_case for others. Not mandatory, but a nice way to distinguish them.

wget $STORE_URL/$1 -O ./$ZIP

Even though in this specific case there are no spaces or other special characters in your variables, always double-quote them to prevent string splitting — there’s simply no reason ever not to do so, and it gets you into the habit of spotting potential errors when quotes are missing.

cd ~/Downloads

That directory might or might not exist. As we’re talking about a GNOME environment, you might want to use something like $(xdg-user-dir DOWNLOAD) to get the actual download directory. The same is usually true for the path ~/.local/share, but the GNOME shell extensions documentation makes it sound as if the path is actually hard-coded.

rm $ZIP

This will not be executed if the script failed earlier due to an error. To ensure cleanup on error or if the user aborted the script, replace this with a trap.

Resulting script:

#!/usr/bin/env bash

# Install a target gnome shell extension defined via url

set -euo pipefail


cd "$(xdg-user-dir DOWNLOAD)"
wget "$store_url/$1" -O "$zip"
trap 'rm "$zip"' ERR INT TERM EXIT

uuid=$(unzip -c "$zip" metadata.json | grep uuid | cut -d \" -f4)

if [[ ! -d "$extensions_path/$uuid" ]]; then
    mkdir "$extensions_path/$uuid"
    unzip -q "$zip" -d "$extensions_path/$uuid"
    gnome-shell-extension-tool -e "$uuid"

gnome-shell --replace &

1 On macOS, on the other hand, it’s a bad idea since the Bash version of /bin/bash is eternally stuck at 3.2 due to licensing issues, and if you want to use any more recent Bash features you need to rely on a user-installed version with a different path.

  • \$\begingroup\$ Thanks for the revision! Trap, double quotes and error checking will get in to my bash code mores \$\endgroup\$
    – artu-hnrq
    Commented Jun 3, 2020 at 1:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.