Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question

3 Answers 3

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
share|improve this answer
    
While this is doubtless correct I find that dpkg-query -l "$package" | grep -q ^.i is usually sufficient (and easier to remember). –  phogg May 22 '12 at 10:54
1  
@phogg: Yes, depends on whether it is supposed to live in a script or not. Also, the dpkg-query -l output is not set in stone since it is just a user presentation mode, so if the presentation changes perhaps such a script would break. –  Daniel Andersson May 23 '12 at 10:30
    
@Daniel. I like the return code approach. Please see my answer with details in code. –  tahoar May 23 '12 at 12:46
    
On 10.04 the format option db:Status-abbrev doesn't seem to exist -- I used: dpkg-query -Wf'${Version}' ${pkg} 2>/dev/null | grep -q '^\d*' to the same effect. –  scooterXL Oct 11 '12 at 13:41

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.

share|improve this answer
    
Well, your code examples are not what I said you should do, but I guess you have just missed the grep part in your pasting. I can't really reproduce your issue, but that might be because the code examples are currently incomplete, so please fix that. Do you run Debian or Ubuntu? –  Daniel Andersson May 23 '12 at 13:18
    
I'm running Ubuntu 10.04 (are PPA's supported no straight Debian?). My code dropped the your grep because 1) the dkpg-query command writes nothing to stdout and grep always throws a returncode. The dpkg-query returncode is 0 if installed. –  tahoar May 23 '12 at 14:29
1  
1. Don't tag your post "Debian" then. 2. I don't think you understood the part grep played in the command, so you stripped it, and now you say it doesn't work? grep -q gives return code 1 if it doesn't match, i.e. the program is not installed or unavailable, or 0 if the program is installed. I explained that in my post. –  Daniel Andersson May 24 '12 at 9:05
#!/bin/bash

# Check for dependencies 
check_deps () {
DEPS=$(echo {dialog,sqlite3,openssh-client})
for i in $DEPS ; do
    dpkg-query -W -f='${Package}\n' | grep ^$i$ > /dev/null
    if [ $? != 0 ] ; then
        echo "Installing deps ..."
        aptitude install $i -y > /dev/null
    fi
done  
}

# execute the check_deps function
check_deps
share|improve this answer
    
-1, the question is not about dependency checking. Also, explain what the parts of the command is doing: otherwise other people can't see what's going on. –  Daniel Andersson Feb 11 '13 at 16:55
    
DEPS=$(echo {dialog,sqlite3,openssh-client}) can be equivalently written as just DEPS="dialog sqlite3 openssh-client". –  Daniel Andersson Feb 11 '13 at 16:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.