Short answer
The first command
aptitude search '?and(?installed,?origin(backports))'
finds packages that are installed and
have a backport available,
but the backport is not necessarily installed.
(Maybe the backport is installed, maybe it isn't.)
By contrast, the second command
aptitude search '?narrow(?installed,?origin(backports))'
finds package that are installed,
and the currently installed version is from a backport,
i.e. the backports that are actually installed.
This is a more restrictive search,
because the set of installed backports is a subset of available backports.
You can think of it like this:
On your system, the first command returns results
but the second returns nothing.
This means that you have installed packages with backports available,
but evidently none of those backports are currently installed.
Long answer
It has to do with aptitude's distinction between
matching the package and matching the package version.
From the
documentation:
There is a subtle, but important, distinction between matching a pattern
against a package, and matching it against all the versions of that
package. When a pattern is matched against a package, each of its terms is
matched against the package, and so each term will match if any version
of the package matches. In contrast, when a pattern is matched against each
version of a package, it will successfully match if it matches when all its
terms are matched against the same version of the package.
For example: suppose that version 3.0-1
of the package aardvark
is
installed, but that version 4.0-1
is available. Then the search
expression ?version(4\.0-1)?installed
matches aardvark, because
?version(4\.0-1)
matches against version 4.0-1
of aardvark, while
?installed
matches against version 3.0-1
. On the other hand, this
expression does not match against all the versions of aardvark
, because
no single version is installed and also has a version number of 4.0-1
.
The documentation
for ?and
reads:
?and(pattern1, pattern2), pattern1 pattern2
Matches packages that match both pattern1 and pattern2.
Note that this matches packages, not single versions. So this query:
aptitude search '?and(?installed, ?origin(backports))'
gets a list of all the package versions that are installed,
then a list of all the package versions
with an origin matching the regular expression backports
,
and then returns the packages that appear in both lists.
On the other hand,
the documentation
for ?narrow
reads:
?narrow(filter, pattern), ~S filter pattern
Select packages for which a single version matches both filter and pattern.
So that's why this query only shows packages
where the single installed version has an origin that matches backports
:
aptitude search '?narrow(?installed, ?origin(backports))'
There is a related discussion
for the ?any-version
function:
?any-version(pattern)
Matches a package if any one of its versions matches the enclosed pattern.
Note: This term is closely related to ?narrow
. In fact,
?any-version(pattern1 pattern2)
is exactly the same as
?narrow(pattern1, pattern2)
.
Note: To be precise, as with any other pattern, it is not packages but
versions of the packages which are matched. For aptitude search
and other
uses it does not make much difference, but aptitude versions
will only
show the versions that match, not all versions of the package for which any
version matches.
By running aptitude versions
instead of aptitude search
,
we find that these queries all give the same result:
aptitude versions '?and(?installed, ?origin(backports))'
aptitude versions '?installed?origin(backports)'
aptitude versions '?narrow(?installed, ?origin(backports))'
Whew!
If you find the query language for aptitude
confusing (as I do),
you may prefer to use a different approach,
such as Python's bindings to libapt
.
Rather than matching on version strings,
you can check the origin string directly, like this:
import apt
apt_cache = apt.Cache()
for pkg in apt_cache:
if pkg.is_installed:
for pkg_origin in pkg.installed.origins:
if pkg_origin.origin == 'Debian Backports':
print(pkg.name)