7

How do I find out what packages have been installed since the OS was installed? I do not want to know all packages installed, only those that were not part of the initial OS install, and have been explicitly installed afterwards.

For the sake of this question, lets assume a fresh install, as I imagine distro upgrades would complicate matters. I would prefer to use command line, but a GUI solution would be OK if a command or script is not available.

I've had a quick look at the man pages of dpkg and aptitude, but didn't see anything obvious. Also, the output of apt-cache show package-name or dpkg -s pkg-name doesn't seem to give any dates that can be compared against the date of OS installation (which I would have to work out how to get too).

I have logwatch on a server that sends daily notifications of what has been installed. My guess is that it parses dpkg.log. I'm not sure this method would be a solution, as many of the install entries may have been logrotated out, especially on older systems. And ideally this should work for any system, desktop or server.

It would also be great if the output could include the version of the package currently installed, but that may be asking too much, and I can always script it later once I have the package names.

5
  • 1
    I don't want to list 'all' installed packages, only those installed after the OS was installed. For example, the dpkg --get-selections | grep -v deinstall command outputs packages like xorg and wget - which would have been part of the initial install. I will edit the question.
    – drgrog
    May 12, 2014 at 8:59
  • 1
    a diff between dpgk --get-selections 's output and this file will do something what you're looking for
    – Ayush
    May 12, 2014 at 9:07
  • Thanks. I have found a more accurate duplicate at unix.stackexchange.com/questions/3595/… - and the answer unix.stackexchange.com/a/80520/9132 is the closest so far, the manifest method seemed to give me everything on one machine (as if comm wasn't working), plus aptitude was not installed on another machine.
    – drgrog
    May 12, 2014 at 14:44
  • @karel the answer by bci, using the history.log, will not give you a full list if the logs do not go as far back as the original install
    – drgrog
    May 12, 2014 at 14:53
  • @drgrog I can understand your point of view. What you have done is an improvement on answers that have already been posted by others and not a duplicate and your question is a worthy question and not a duplicate.
    – karel
    May 12, 2014 at 16:44

3 Answers 3

7

All Ubuntu ISO ([UKLX]buntu/Ubuntu-gnome) comes with .manifest file that contains the list of all pre-installed packages in the ISO. You can find those manifest files in the same download dir as those ISO on any Ubuntu ISO mirrors. Take the list of available Ubuntu releases as an example; if you have Trusty 64-bit for example, the manifest link would be http://releases.ubuntu.com/trusty/ubuntu-14.04.2-desktop-amd64.manifest.

So once you have this file, just compare the package listing in it against the listing of all installed packages in your Ubuntu using comm command

$ curl -O http://releases.ubuntu.com/trusty/ubuntu-14.04-desktop-amd64.manifest
$ comm -23 <( dpkg --get-selections | awk '$2 ~ /^(install|hold)/ { print $1 }' | sort ) \
        <( awk '{ print $1 }' ubuntu-14.04-desktop-amd64.manifest | sort )

To explain what the comm does, it takes input from 2 files - first one supplies the list of all currently installed packages and the second one the manifest file. The -3 opt suppresses lines that both files have and -2 suppresses lines that only the second file (manifest file, that is) has. So in the end your output contains only lines that only file one has and that gives you packages that you installed manually since the OS was installed.

So there you have it.

Edit

If you'd also like to see the package version next to package name in the output, as Slyvain Pineau pointed out, pipe the comm command above to xargs dpkg-query -W -f='${binary:Package} ${Version}\n' so it becomes

$ comm -23 <( dpkg --get-selections | awk '$2 ~ /^(install|hold)/ { print $1 }' | sort ) \
           <( awk '{ print $1 }' ubuntu-14.04-desktop-amd64.manifest | sort ) | \
           xargs dpkg-query -W -f='${binary:Package} ${Version}\n

Or alternatively, with awk entirely, This too give the same result as command above

awk 'FNR==NR {arr[$1];next} !($1 in arr) { print $0 }' ubuntu-14.04-desktop-amd64.manifest <( dpkg-query -W -f='${binary:Package} ${Version}\n' )

See this link for explanation on how the awk cmd work

2
  • @Sylvain Pineau - dpkg-query doesn't take input from stdin
    – Flint
    May 12, 2014 at 11:27
  • Sorry. Next time I'll double check. It should be [...] | xargs dpkg-query -W -f='${binary:Package} ${Version}\n'. Feel free to edit your answer with the version addition :) May 12, 2014 at 11:36
4

The initial-status.gz and dpkg-query method from https://unix.stackexchange.com/a/80520/9132 gives the most accurate and concise list for my needs.

comm -13 \
  <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort) \
  <(comm -23 \
    <(dpkg-query -W -f='${Package}\n' | sed 1d | sort) \
    <(apt-mark showauto | sort) \
  )

Why I like it, and not the others:

The manifest comparison method from Flint's answer and from https://unix.stackexchange.com/a/3624/9132 includes many dependencies and other packages possibly marked as 'required' and installed automatically. For example, it lists libvlc5 and vlc-data, whereas the method above only lists vlc.

The history.log method from https://askubuntu.com/a/250530/16741 will not list all packages if the logs do not go back as far as the release install. It also contains a lot of upgrade commands that would need to be filtered out.

The dpkg --get-selections method, which is an accepted answer from a similar question, lists all packages and dependencies, including those installed with the release. It does not list only those installed explicitly.

0

Big thanks and congratulations to those who came up with that gem of a script !!!
I wanted to add my 2¢ and I tacked the installation date I deduce from $info.
I did not master the details why $info files are updated or not and when, but it works in practice.
My script lists the latest updates of non dependency packages added after installation.
Giving it a periodic check, I was seeing what I would have manually logged without a single miss.
That is, batches of packets installed for the same reason. Unfortunately, updates break that order.
After a system upgrade, I had a list of my added packages that the upgrade did not update followed by those that it did.
Neat! Enjoy.

info='/var/lib/dpkg/info/'

comm -13 > /tmp/packages \
  <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort) \
  <(comm -23 \
    <(dpkg-query -W -f='${Package}\n' | sed 1d | sort) \
    <(apt-mark showauto | sort) \
  )

while read n; do
  echo $(ls -ltr --time-style=long-iso $info$n.* $info$n:i386.* $info$n:amd64.* 2>/dev/null \
    | tail -n 1 | perl -pe 's/.*([0-9]{4}?-.*:[0-9]{2}?).*/\1/') $n
done < /tmp/packages | sort

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .