61

In Gentoo there is the file /var/lib/portage/world that contains packages that I explicitly installed. By explicit I mean, packages that I choose, not including anything installed by default, or pulled in by the dependencies.

Is there a similar file or a command to find that information in Ubuntu?

tshepang
  • 65,642
phunehehe
  • 20,240

10 Answers10

53

Just the code

aptitude search '~i !~M' -F '%p' --disable-columns | sort -u > currentlyinstalled.txt
wget -qO - http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest \
  | cut -f1 | sort -u > defaultinstalled.txt
comm -23 currentlyinstalled.txt defaultinstalled.txt

Explanation

One way to think about this problem is to break this into three parts:

  • How do I get a list of packages not installed as dependencies?
  • How do I get a list of the packages installed by default?
  • How can I get the difference between these two lists?

How do I get a list of packages not installed as dependencies?

The following command seems to work on my system:

$ aptitude search '~i !~M' -F '%p' --disable-columns | sort -u > currentlyinstalled.txt

Similar approaches can be found in the links that Gilles posted as a comment to the question. Some sources claim that this will only work if you used aptitude to install the packages; however, I almost never use aptitude to install packages and found that this still worked. The --disable-columns prevents aptitude from padding lines of package names with blanks that would hinder the comparison below. The | sort -u sorts the file and removes duplicates. This makes the final step much easier.

How do I get a list of the packages installed by default?

Note: This section starts out with a 'wrong path' that I think is illustrative. The second piece of code is the one that works.

This is a bit trickier. I initially thought that a good approximation would be all of the packages that are dependencies of the meta-packages ubuntu-minimal, ubuntu-standard, ubuntu-desktop, and the various linux kernel related packages. A few results on google searches seemed to use this approach. To get a list of these dependencies, I first tried the following (which didn't work):

$ apt-cache depends ubuntu-desktop ubuntu-minimal ubuntu-standard linux-* | awk '/Depends:/ {print $2}' | sort -u

This seems to leave out some packages that I know had to come by default. I still believe that this method should work if one constructs the right list of metapackages.

However, it seems that Ubuntu mirrors contain a "manifest" file that contains all of the packages in the default install. The manifest for Ubuntu 12.04.3 is here:

http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest

If you search through this page (or the page of a mirror closer to you):

http://mirror.pnl.gov/releases/precise/

You should be able to find the ".manifest" file that corresponds to the version and architecture you are using. To extract just the package names I did this:

wget -qO - http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest | cut -f1 | sort -u > defaultinstalled.txt

The list was likely already sorted and unique, but I wanted to be sure it was properly sorted to make the next step easier. I then put the output in defaultinstalled.txt.

How can I get the difference between these two lists?

This is the easiest part since most Unix-like systems have many tools to do this. The comm tool is one of many ways to do this:

comm -23 currentlyinstalled.txt defaultinstalled.txt

This should print the list of lines that are unique to the first file. Thus, it should print a list of installed packages not in the default install.

Steven D
  • 46,160
  • What does your first pipeline do that aptitude search '~i!~M' -F %p doesn't? – ephemient Oct 30 '10 at 04:57
  • @ephemient: Probably nothing. I don't know much about aptitude and thus used tools I'm familiar with rather than digging around in the man file of a program I never use. – Steven D Oct 30 '10 at 16:38
  • 1
    You kind of destroy my hope, I thought there was some standard easy way :( – phunehehe Nov 02 '10 at 01:31
  • Heh, so did I. I'm not an Ubuntu guru so I'd be happy to see an easier solution if somebody can find one. – Steven D Nov 02 '10 at 04:29
  • It seems the aptitude line leaves lots of whitespace at the end of each line. To remove it, add | sed "s/ *$//" to the pipeline. – Emil Styrke May 23 '14 at 17:38
  • for your first step, you might want deborphan -a – josinalvo Jul 02 '14 at 17:10
  • actually, deborphan -a | awk '{ print $2 }' | sort -u > currentlyinstalled.txt – josinalvo Jul 02 '14 at 17:59
  • 3
    This almost works, but still isn't correct. There are multiple packages and libraries that I certainly didn't install manually contained in the resulting list. I used http://releases.ubuntu.com/releases/trusty/ubuntu-14.04-desktop-amd64.manifest and the additional | sed "s/ *$//" but still no dice. – jmiserez Jul 06 '14 at 14:14
  • @jmiserez Hrm, it has been a while since I've looked at this one. Do you have the list of packages that this missed? – Steven D Jul 08 '14 at 08:46
  • On my system, it's 595 packages. You can see the list and a detailed comparison here. That is with the extra sed and the correct manifest file for my system. – jmiserez Jul 08 '14 at 13:06
  • See also the answer I posted below. I modified your approach just a bit. – jmiserez Jul 09 '14 at 00:45
  • Some sources claim that this will only work if you used aptitude to install the packages; however, I almost never use aptitude to install packages and found that this still worked. that's because that hasn't been true for several years now. It used to be the case that aptitude and apt-get used different databases to record which packages were installed automatically but this has not been the case for a number of stable Debian versions ie many years. Old advice tends to stick around after it's no longer true. – trr Oct 22 '14 at 08:36
  • If you just install a fresh (whatever) linux, you can just save the installed packages to defaultinstalled.tx Then, use the comm command part :) – Michahell May 01 '15 at 23:28
  • 1
    The first step that gets a list of packages not installed as dependencies can be replaced with apt-mark showmanual | sort -u, as shown in other answers. Simpler, and does not rely on aptitude which is not installed by default. – skagedal May 03 '15 at 06:44
  • The http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest URL in this solution is now a 404, making this answer (currently) worthless, unfortunately. Since this question turns up 4th in a Google search for "linux mint list of manually installed packages", it's probably worth updating that URL to something that works. – rmunn Jan 11 '16 at 02:09
  • This is imperfect, but here's how I've generated the "defaultinstalled.txt" file: wget -qO - https://releases.ubuntu.com/$(grep -oP 'VERSION_CODENAME=\K.+' /etc/os-release)/ubuntu-$(grep -oP 'VERSION= "\K[0-9\.]+' /etc/os-release)-desktop-amd64.manifest | cut -f1 | cut -d: -f1 | sort -u > defaultinstalled.txt (replace the amd64 as needed). – Tyn Apr 08 '20 at 07:17
  • (I unfortunate cannot edit my comment anymore: the space after VERSION= needs to be removed).

    Otherwise, convenient one-liner: comm -23 <(apt-mark showmanual | sort -u) <(curl -s -- https://releases.ubuntu.com/$(grep -oP 'VERSION_CODENAME=\K.+'/etc/os-release)/ubuntu-$(grep -oP 'VERSION="\K[0-9\.]+' /etc/os-release)-desktop-amd64.manifest | cut -f1 | cut -d: -f1 | sort -u)

    – Tyn Apr 08 '20 at 07:28
26

You can use either of these two one-liners. Both yield the exact same output on my machine and are more precise than all solutions proposed up until now (July 2014) in this question. They are a combination of the two answers (1) and (2). Note that I originally posted this answer here.

Using apt-mark:

comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)

Using aptitude:

comm -23 <(aptitude search '~i !~M' -F '%p' | sed "s/ *$//" | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)

Very few packages still fall through the cracks, although I suspect these are actually installed by the user, either right after the installation through the language localization setup or e.g. through the Totem codec installer. Also, the linux-header versions also seem to accumulate, even though I've only installed the non version-specific metapackage. Examples:

libreoffice-help-en-gb
openoffice.org-hyphenation
gstreamer0.10-fluendo-mp3
linux-headers-3.13.0-29    

How does it work

  1. Get the list of manually installed packages. For aptitude, the additional sed strips out remaining whitespace at the end of the line.
  2. Get the list of packages installed right after a fresh install.
  3. Compare the files, only output the lines in file 1 that are not present in file 2.

Other possibilities don't work as well:

  • Using the ubuntu-14.04-desktop-amd64.manifest file (here for Ubuntu 14.04) instead of /var/log/installer/initial-status.gz. More packages are shown as manually installed even though they are not.
  • Using apt-mark showauto instead of /var/log/installer/initial-status.gz. apt-mark for example doesn't include the xserver-xorg package, while the other file does.

Both list more packages than the above solution.

jmiserez
  • 506
  • 4
  • 10
15

According to man apt-mark:

apt-mark showauto
apt-mark showmanual
Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
mmaruska
  • 269
8

Here's some sample output of cat /var/log/apt/history.log:

Start-Date: 2011-01-22  00:43:38
Commandline: apt-get --target-release experimental install libdbus-1-dev
Upgrade: libdbus-1-3:i386 (1.4.0-1, 1.4.1-1), libdbus-1-dev:i386 (1.4.0-1, 1.4.1-1)
End-Date: 2011-01-22  00:43:48

Start-Date: 2011-01-23  01:16:13
Commandline: apt-get --auto-remove purge webcheck
Purge: python-utidylib:i386 (0.2-6), python-beautifulsoup:i386 (3.1.0.1-2), libtidy-0.99-0:i386 (20091223cvs-1), webcheck:i386 (1.10.3)
End-Date: 2011-01-23  01:16:31

As for your question, filter the stuff with grep (cat /var/log/apt/history.log | grep Commandline).

Note that these files are rotated, so check for others so you don't miss anything:

$ ls /var/log/apt/history.log*
-rw-r--r-- 1 root root 69120 2011-01-23 18:58 /var/log/apt/history.log
-rw-r--r-- 1 root root 19594 2011-01-01 02:48 /var/log/apt/history.log.1.gz

NOTE:

  • I've checked both aptitude and synaptic (versions 0.70 and 0.6.3 respectively), and they both log their activities on that log file. The one setback with them is that they don't have the line starting with Commandline, so the grep trick won't work with them.
tshepang
  • 65,642
  • 2
    Interesting solution. You'll need to adjust the grep command a bit to just get a list of packages and to account for packages installed by aptitude and other package managers. If your logs have rotated away, well then you are out of luck. – Steven D Jan 23 '11 at 22:27
  • @steven Updated. My grep-fu is of a novice, so I'll leave that to the reader. Also, I don't know if the thing rotates away. I only have to files in there myself. – tshepang Jan 23 '11 at 23:03
  • Whether they rotate away will depend on your logrotate setup and how long your system has been around. I'm unsure of Ubuntu defaults since it has been a long time since I changed them. – Steven D Jan 24 '11 at 03:40
7

I came across this beautiful oneliner while I was searching for this query

The one liner is

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) \
  )`

This oneliner filters packages installed by system using logs from /var/log/installer/initial-status.gz

I will post the link to the original thread when I found it, as this oneliner is not mine and and I can't seem to remember where I saw it.

Glorfindel
  • 815
  • 2
  • 10
  • 19
Archit
  • 187
2

You would want to have a look at this article.

At the end of the article, there is a python script that should do what you want.

It was written for (k)ubuntu. but should work for Ubuntu aswell.

Xan
  • 103
Stefan
  • 25,300
2

This is an addition to Steven D's answer.

The following line truncates package names at 32 characters:

aptitude search '~i !~M' | cut -d" " -f4 | sort -u > currentlyinstalled.txt

This seems to work:

aptitude search '~i !~M' -F "%p" | sort -u > currentlyinstalled.txt

see this answer

1

Check out /var/log/apt/term.log

Joril
  • 566
  • 2
    that's a rather painful way to do things, and there is no distinction between packages I install myself, and those pulled in by dependencies – phunehehe Oct 29 '10 at 07:18
  • I agree, but I didn't know that apt keeps track of those :/ Now I know, thanks to Stefan :) – Joril Oct 29 '10 at 14:00
1

You may also look at the file /var/lib/apt/extended_states.

cat /var/lib/apt/extended_states | grep -B2 'Auto-Installed: 0'

This is useful if you want to know what was installed on an old partition.

GAD3R
  • 66,769
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
Papou
  • 41
  • 3