I didn't see any solutions here work for me, I have installed quite a few deb packages with dpkg and a few of the items I was particularly looking for were missing.
A rather lengthy one liner, but convenient to copy and paste would be:
export DPKG_INITIAL=$(mktemp) DPKG_INSTALLED=$(mktemp) DPKG_CUSTOM=$(mktemp) DPKG_DEPS=$(mktemp) zgrep -E '^Package' /var/log/installer/initial-status.gz | awk '{ print $2 }' > $DPKG_INITIAL ; awk '$3 !~ /install|remove|purge/ { next } { gsub(/remove|purge/, "uninstall", $3) ; gsub(/:.+/, "", $4) ; a[$4]=$3 } END { for (p in a) { if (a[p] == "install") { print p } } }' /var/log/dpkg.log | sort -u > $DPKG_INSTALLED ; comm -23 installed initial > $DPKG_CUSTOM ; function rdep() { apt-cache rdepends $1 | tail -n +3 | sed -e 's/^ //' -e '/^ /d' | cut -d':' -f1 | sort -u; } ; echo "$(for i in $(cat custom) ; do rdep $i ; done)" | sort -u > $DPKG_DEPS ; comm -23 custom deps > my-packages ; rm $DPKG_INITIAL $DPKG_INSTALLED $DPKG_CUSTOM $DPKG_DEPS
The above command saves a list of packages to a file in your current working directory named my-packages
.
Explanation
I first built a list of packages that composed the baseline of packages selected during installation.
zgrep -E '^Package' /var/log/installer/initial-status.gz | awk '{ print $2 }' > initial
Followed by a long list of items installed in general.
awk '$3 !~ /install|remove|purge/ { next } { gsub(/remove|purge/, "uninstall", $3) ; gsub(/:.+/, "", $4) ; a[$4]=$3 } END { for (p in a) { if (a[p] == "install") { print p } } }' /var/log/dpkg.log | sort -u > installed
I then compared the two files initial
and installed
to list only the items unique to installed.
comm -23 installed initial > custom
From there I wanted to filter out the dependencies, this is where this method may miss some desired packages, it is unaware of dependencies that are also explicitly installed.
I wrote a quick bash function to shorten this steps in processing these items.
function rdep() { apt-cache rdepends $1 | tail -n +3 | sed -e 's/^ //' -e '/^ /d' | cut -d':' -f1 | sort -u; }
After that I passed each line from my file custom
into this function with xargs
.
echo "$(for i in $(cat custom) ; do rdep $i ; done)" | sort -u > deps
Once I had the long list of every possible dependency, (not sure on the every possible statement), I once again got the lines that were unique to a single file.
comm -23 custom deps > manual
And my finished list of packages is now in a file named manual
available for me to review.
apt list --manual-installed=true
orapt-mark showmanual
(can be cross-checked with Synaptic Package Manager under "Installed (manual)")