Debian – List top level manually installed packages without their dependencies

aptdebdebianUbuntu

There are many ways to show packages installed manually using apt, such as:

apt-mark showmanual

But sometimes that output is too much. For example if the user manually installed package foo:

apt-get install foo

…and foo depended on bar and baz, then apt-mark showmanual would output:

bar
baz
foo

How can we list only the top level manually installed packages (i.e. foo) without their dependencies (i.e. not baz, nor bar)?


The following code seems to work, but GNU parallel calling apt-rdepends a few hundred times is too slow, (three hours with a 4 core CPU):

apt-mark showmanual | 
tee /tmp/foo | 
parallel "apt-rdepends -f Depends,PreDepends,Suggests,Recommends {} |
          tail +2" 2> /dev/null | 
tr -s ' ' '\n' | 
grep -v '[():]' | 
sort -Vu | 
grep -wv -f - /tmp/foo

Best Answer

This could be done using the Python apt API. The packages you see in apt-mark showmanual are exactly the ones in apt.cache.Cache() for which is_installed is true and is_auto_installed is false. But, it's easier to process the dependencies:

#! /usr/bin/env python3

from apt import cache

manual = set(pkg for pkg in cache.Cache() if pkg.is_installed and not pkg.is_auto_installed)
depends = set(dep_pkg.name for pkg in manual for dep in pkg.installed.get_dependencies('PreDepends', 'Depends', 'Recommends') for dep_pkg in dep)

print('\n'.join(pkg.name for pkg in manual if pkg.name not in depends))

Even this lists some packages which I would not expect to see there (init, grep?!).

Related Question