11

In the following question there is a solution to checking for a package prior to installing it:

How do I check if a package is installed on my server?

However, I have found that this does not work for Virtual Packages.

Is there a way to traverse the package name that apt-get automatically select and check for the correct one?

Noki
  • 932

4 Answers4

15

Apt will not install a virtual package unless there is only one provider for it. If another package depends on a virtual package, it usually also names a real package as an alternative (i.e. build-essential depend on "libc6-dev | libc-dev" - the second being a virtual package).

Virtual packages are not installed, thus you cannot check their status. You can use apt-cache showpkg <pkg-name> to view which packages provide the virtual package, and then check whether any of these are installed.

  • 1
    See property Reverse Provides in the output. – darkdragon Jun 23 '20 at 06:01
  • In my case, this answer helped me. I installed a package that suggested another package. While I searched information for it, I got the Can't select versions from package 'dovecot-common' as it is purely virtual error. Using this answer, I was able to find which package name I had pass to apt-cache show (and install). – apaderno Nov 08 '20 at 21:42
6

You can use grep-status (package dctrl-tools, not installed by default) to find all installed packages providing some virtual package:

$ grep-status -FProvides,Package -sPackage,Provides,Status awk 
Package: mawk
Provides: awk
Status: install ok installed

Package: gawk
Provides: awk
Status: install ok installed
1

@FlorianDiesch'answer looks interesting, but I want something without need for any software not installed by default.

I ended up using this:

function check_packages_and_install_if_absent()
{
    for PACKAGENAME
    do
        if
            dpkg -l "$PACKAGENAME" | grep ^ii
        then
            echo "Package $PACKAGENAME is present"
            continue
        fi

        FOUND=""

        while read ACTUALPACKAGENAME
        do
            echo "$PACKAGENAME is a virtual package, that can be provided by $ACTUALPACKAGENAME"

            if
                dpkg -l "$ACTUALPACKAGENAME" | grep ^ii
            then
                echo "Actual package $ACTUALPACKAGENAME is present"
                FOUND=true
                break;
            fi

        done < <( apt-cache showpkg "${PACKAGENAME}" | sed -e '1,/^Reverse Provides: *$/ d' -e 's/ .*$//' | sort | uniq )

        # Using sed to print lines after match
        # https://stackoverflow.com/questions/32569032/sed-print-all-lines-after-match#answer-32569573

        if [[ "$FOUND" == "true" ]]
        then
            continue
        fi

        echo "Package $PACKAGENAME is absent, installing"
        sudo apt-get install -y "$PACKAGENAME"
    done
}

You can call it with a list of normal and/or virtual package names:

function check_packages_and_install_if_absent foo bar baz
-3

You can query the database of installed packages for packagename with

dpkg -l packagename   

And you can list all the files in packagename with

dpkg -L packagename

Read man dpkg for more information, like how to use wildcards.

waltinator
  • 36,399