'List manually installed apt packages on Debian 10 (Buster)

It was always nice to see which packages I manually installed using apt install.

Because I could then remove the packages I no longer need.

But I can't find a command working on Debian 10 (Buster) with APT version 1.8.2.

Is there a command showing all manually packages without their dependencies?

I tried the commands in these posts:



Solution 1:[1]

This Bash command will print all manually installed packages minus the ones that came from your Debian installation (in other words, the packages that you installed with apt install):

sudo grep -oP "Unpacking \K[^: ]+" /var/log/installer/syslog \
  | sort -u | comm -13 /dev/stdin <(apt-mark showmanual | sort)

It was tested in Debian 10 (Buster). sudo is needed to search through /var/log/installer/syslog. You could also save this installer package list somewhere else if you don't want to use sudo every time.

Solution 2:[2]

You can get a list of apt/apt-get installed packages by grepping /var/log/apt/history.log*

grep_apt_history.bash:

#!/usr/bin/env bash

# current apt history
grep "apt.* install" /var/log/apt/history.log | grep -v broken \
    | grep -Po 'install\s\K.*' | sort -u

# zipped apt history
gzip -cd $(find /var/log/apt -name "history.log.[0-9]*.gz") \
    | grep "apt.* install" | grep -v broken | grep -Po 'install\s\K.*' | sort -u

parse_apt_install.py:

#!/usr/bin/env python3
import sys

installed_packages = []
avoid = ['--no-install-recommends', '--yes', '-y', '--reinstall']

for line in sys.stdin:
    if ' ' in line:
        packages = line.split(' ')
        for package in packages:
            if not package in avoid:
                installed_packages.append(package.strip('\n'))
    else:
        stripped = line.strip('\n')
        if not './' in stripped:
            installed_packages.append(stripped)


for package in sorted(installed_packages):
    print(package)

The python script will remove packages installed locally './'

Usage:
./grep_apt_history.bash | ./parse_apt_install.py

Solution 3:[3]

Wrote this script to replay the apt history logs, producing a list of what was installed manually and is still installed. A little hacky and there may be undiscovered exceptions, but it works on Debian 11 and Mint 20. Explanations are in the code comments.

#!/bin/bash

PROGRAM_LIST=() # array to hold programs
EARLIEST_RECORD="$( zgrep . /var/log/apt/history.log* | grep Start-Date | sed 's@Start-Date: @@g; s@  @ @g;' | sort -d | head -n 1 )" # find earliest log entry (zgrep handles gzipped and uncompressed input)

prepare_sorted_log() {
  # select any operations *requested*, plus precededing two lines (date and command)
    # select only relevant operations and preceding line (date)
    # collapse to one line
    # separate individual actions using grep's group separator, compress spaces, remove starting text
    # reduce to date, action, and programs only
    # sort by date (first columns)
    # remove apt* flags and leading text
  zgrep -h Requested /var/log/apt/history.log* -B 2 \
    | egrep -B1 ' (install|remove|purge)' \
    | tr '\n' ' ' \
    | sed -r 's@ -- @\n@g; s@  @ @g; s@Start-Date: @@g;' \
    | sed -r 's@Commandline: .*(install|remove|purge)(.*)@\1\2@g;' \
    | sort \
    | sed -r 's@ \-+[A-Za-z]+( |$)@ @g; s@.*(install|remove|purge) @\1 @g;' 
}

install() {
  for program in ${@}; do
    [[ "${program}" =~ DPkg.* ]] && return # filter exceptions (add more with |)
    echo -n "Found installation of ${program}; adding to list ... "
    PROGRAM_LIST+=(" ${program} ") && echo "done" || echo "ERROR" # add to array since install was requested
  done
}

remove() {
  for program in ${@}; do
    echo -n "Found removal of ${program}; removing from list ... "
    PROGRAM_LIST=( "${PROGRAM_LIST[@]/ ${program} }" ) && echo "done" || echo "ERROR" # remove from array since remove or purge was requested
  done
}

purge() {
  remove ${@} # remove and purge are the same for our purposes
}

while read line; do
  eval "${line}" # run function based on action
done <<< "$( prepare_sorted_log )" # read prepared and sorted log

echo -e "\nPrograms installed manually and not subsequently removed (since ${EARLIEST_RECORD}):\n$( echo "${PROGRAM_LIST[@]}" | tr ' ' '\n' | sort -u )" # display sorted list
echo -e "\nInstallation paste:\n\napt install$( echo "${PROGRAM_LIST[@]}" | sed -r 's@ +@ @g' )" # display command to install (e.g., on new system)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Mortensen
Solution 2
Solution 3 user108151