HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Bash script that checks for package dependencies and installs them if necessary

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptnecessarypackagechecksinstallsthatforandthembash

Problem

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

Solution

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.

Code Snippets

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

Context

StackExchange Code Review Q#88392, answer score: 3

Revisions (0)

No revisions yet.