Reliably check if a package is installed or not
I have a simple requirement. I want to define several variables that will correspond to any number of given packages I want to install via a shell script.
Sample code below:
MISC="shutter pidgin"
WEB="apache2 mongodb"
for pkg in $MISC $WEB; do
if [ "dpkg-query -W $pkg | awk {'print $1'} = """ ]; then
echo -e "$pkg is already installed"
else
apt-get -qq install $pkg
echo "Successfully installed $pkg"
fi
done
Everything kinda works, but the logic seems flawed because it's not reliably installing the packages I want. It either says they've been installed already or it's trying to install packages that have already been installed previously.
I've also been trying with command -v
or the following:
if [ "dpkg -l | awk {'print $2'} | grep --regexp=^$pkg$ != """ ]; then
And even with the -n
and -z
flags to check if the returned string was empty. Pretty sure I'm missing some good sense here.
Do you have any idea what I could do to make sure a package is actually installed or not?
Thanks!
Essentially you only need to replace the if
condition with
if dpkg --get-selections | grep -q "^$pkg[[:space:]]*install$" >/dev/null; then
It is not possible to use dpkg-query
, because it returns true also for packages removed but not purged.
Also I suggest to check the exit code of apt-get
before giving the successful message:
if apt-get -qq install $pkg; then
echo "Successfully installed $pkg"
else
echo "Error installing $pkg"
fi
You can test it by dpkg-query:
if dpkg-query -W -f'${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then
Note that * and ? are wildcards, if they appear in $pkg. I guess dpkg-query may print "reinst-required installed" instead of "ok installed", if package is broken and needs to be reinstalled by command apt-get install --reinstall
which can be used to install new packages as well.