How to check if a virtual package is installed?

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?


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.


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

@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