4
\$\begingroup\$

I'm new to writing bash scripts and was wondering if I could get someone's advice on a part of the script I'm working on.

Intended purpose of code

Check if a package exists using dpkg, and if it doesn't, offer to install it for the user. This snippet is part of a larger script that installs a particular Conky configuration along with all of its dependencies with minimal effort from the user.

Concerns

  • I feel as though there is a more elegant way to check if a package is installed using dpkg (code was found on Stack Overflow).
  • Is there a better way of handling the (y/n) response?

Here is the code that I am using:

declare -a packages=("conky-all" "lm-sensors");
for i in "${packages[@]}"; do
 if [ $(dpkg-query -W -f='${Status}' $i 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
 echo "$i is not installed, would you like to install it now? (Y/N)";
 read response
 if [ "$response" == "y" ] || [ "$response" == "Y" ]; then
 sudo apt-get install "$i";
 else
 echo "Skipping the installation of $i...";
 echo "Please note that this Conky configuration will not work without the $i package.";
 fi
 else
 echo "The $i package has already been installed.";
 fi
done
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 29, 2015 at 19:44
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Instead of this:

 if [ $(dpkg-query -W -f='${Status}' $i 2>/dev/null | grep -c "ok installed") -eq 0 ]; then

A better way to write the same thing:

 if ! dpkg-query -W -f='${Status}' $i 2>/dev/null | grep -q "ok installed"; then

Instead of this:

 if [ "$response" == "y" ] || [ "$response" == "Y" ]; then

A simpler way to write is:

 if [[ $response == [yY]* ]]; then

This is not example the same. It will match anything that starts with "y" or "Y". If you want to match strictly only those letters, just drop the * from the pattern:

 if [[ $response == [yY] ]]; then

Finally, all the ; at line endings are unnecessary. The purpose of ; is to separate multiple statements on the same line. Line breaks naturally serve as statement separators.

answered Apr 29, 2015 at 19:59
\$\endgroup\$
4
  • \$\begingroup\$ Thank you very much. Just for the sake of clarity, why are the double brackets necessary for the "if [[ $response == [yY] ]]" statement? \$\endgroup\$ Commented Apr 29, 2015 at 20:05
  • 1
    \$\begingroup\$ [ ... ] cannot match patterns like that. [[ ... ]] is more modern and sophisticated, it can do this. \$\endgroup\$ Commented Apr 29, 2015 at 20:07
  • 1
    \$\begingroup\$ Just make it a habit to quote all variable expansions. It's not worth it to save a few quote characters. \$\endgroup\$ Commented Apr 30, 2015 at 0:55
  • \$\begingroup\$ @200_success I guess you're right. I dropped that point about quoting \$\endgroup\$ Commented Apr 30, 2015 at 4:48

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.