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
1 Answer 1
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.
-
\$\begingroup\$ Thank you very much. Just for the sake of clarity, why are the double brackets necessary for the "if [[ $response == [yY] ]]" statement? \$\endgroup\$John P.– John P.2015年04月29日 20:05:36 +00:00Commented Apr 29, 2015 at 20:05
-
1\$\begingroup\$
[ ... ]
cannot match patterns like that.[[ ... ]]
is more modern and sophisticated, it can do this. \$\endgroup\$janos– janos2015年04月29日 20:07:22 +00:00Commented 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\$200_success– 200_success2015年04月30日 00:55:39 +00:00Commented Apr 30, 2015 at 0:55
-
\$\begingroup\$ @200_success I guess you're right. I dropped that point about quoting \$\endgroup\$janos– janos2015年04月30日 04:48:58 +00:00Commented Apr 30, 2015 at 4:48