Test if a package is installed in APT

I want a shell script method to test/report if a package is installed. I don't need details, only boolean return to set logic flow. I looked at Find if a package is installed, but dpkg returns complex output and its format changes depending on whether the package is in the Debian repository or in an Ubuntu PPA.

I found that apt-cache does a pretty good job and I came up with this method:

is_installed=0
test_installed=( `apt-cache policy package-name | grep "Installed:" ` )
[ ! "${test_installed[1]}" == "(none)" ] && is_installed=1

Does anyone know a simpler or more direct way?


dpkg-query as in your linked post seems to be the most correct tool for the job, except using e.g. the available Python libraries to bind directly to the APT system in such a scripting context.

With dpkg-query:

dpkg-query -Wf'${db:Status-abbrev}' package-name 2>/dev/null | grep -q '^i'

Will return true (exit status 0 in shell script) if the package is installed, false (exit status 1) otherwise.

  • -W means "Show" (dpkg-query must have a requested action).
  • -f changes the format of the output.
  • db:Status-abbrev is the short form of the package status.
  • 2>/dev/null silences dpkg-query if an invalid package name is given. How this should be handled could be a case-to-case issue.
  • grep -q returns true if there is a match, false otherwise.

If it is used often, it could be made a simple function:

#!/bin/sh
debInst() {
    dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'
}

if debInst "$1"; then
    printf 'Why yes, the package %s _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package %s is not currently installed.\n' "$1"
fi

or just simply

#!/bin/sh
if dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'; then
    printf 'Why yes, the package "%s" _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package "%s" is not currently installed.\n' "$1"
fi

I tested Daniel's suggestions on three packages with these results:

  1. Native Debian repository package not installed:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' apache-perl
    ~$ echo $?
    1
    
  2. PPA package registered on host and installed:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' libreoffice
    ~$ echo $?
    0
    
  3. PPA package registered on host but not installed:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' domy-ce
    ~$ echo $?
    0
    ~$ sudo apt-get remove domy-ce
    [sudo] password for user: 
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Package domy-ce is not installed, so not removed
    0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
    

Although I like the approach, it seems I can't trust the return code with PPA packages. Short of that, I think I'll stick with parsing the return of the apt-cache policy command.