Ubuntu: How to get a list of newly installed packages after time x without removed packages after time x?



Question:

From /var/log/apt/history.log it is possible to retrieve a list of installed and removed packages within time x based on timestamps, but editing the file is rather annoying, so I'm looking for a (set of) command(s) to get the effective list of packages which have been installed after timestamp x_0(= packages which have been installed after timestamp x_0 minus packages which have been removed after timestamp x_0) in form of a list of package names.

software-center only displays changes chronologically and synaptic doesn't have a column which represents installation time. dpkg-query looks promising, but I'd appreciate some help from someone who can figure this out in minutes rather than days (the latter applies to myself).

I'm running Ubuntu 14.10.


Solution:1

It seems that dpkg doesn't show explicitly any information about installation dates of packages.

So, for a single run I would use something like the following one-liner:

cat /var/log/apt/history.log |perl -lne 'next unless /^Start-Date: ([^ ]+)/ && $1 ge "2015-04-26" .. 1; next unless /^(Install|Purge|Remove): (.*)$/; $c = $1; $s = $2; $s =~ s/\([^\)]*\)//g; @packages = map { /^(.*?):/ ? $1 : $_} split /\s*,\s*/, $s; if ($c=~/^Install$/){ $h{$_} = 1 for @packages;} if ($c=~/^(Purge|Remove)$/) {delete $h{$_} for @packages;} END{print for sort keys %h;}'  

Start date (x_0) has been hard-coded in the command ("2015-04-26").

For time to time usage more suitable would be a stand-alone script, like this installed_packages.pl:

#!/usr/bin/perl    # use as follows:  # ./installed_packages.pl '2015-04-26' /var/log/apt/history.log  # or  # ./installed_packages.pl '2015-04-26 16:08:36' /var/log/apt/history.log    use strict;  use warnings;    # the script expects start date as first argument  my $START_DATE = shift @ARGV;    # hash (dict) to accumulate installed & not removed packages   my %installed;  # flag to mark the beginning of "interesting" period of time  my $start = 0;    # loop over lines from the input file  while (my $line = <>){      # remove end-of-line character       chomp $line;        # skip everything until date becomes greater (or equal) than our x_0      $start ||= $line =~ /^Start-Date: ([^ ]+)/ && $1 ge $START_DATE;      next unless $start;        # we're only interested in lines like       # Install: tupi-data:amd64 (0.2+git02-3build1, automatic), tupi:amd64 (0.2+git02-3build1), libquazip0:amd64 (0.6.2-0ubuntu1, automatic)      # or      # Remove: aptitude-common:amd64 (0.6.8.2-1ubuntu4)      # + separate action (install/remove/purge) from package list      next unless $line =~ /^(Install|Purge|Remove): (.*)$/;       my ($action, $packages_str) = ($1, $2);        # remove versions from the list (they're in parentheses)      $packages_str =~ s/\(.*?\)//g;        # split single line into array of package names      my @packages = split /\s*,\s*/, $packages_str;      # remove architecture name (comes after ':')      s/:.*// for @packages;        # if packages have been installed, add them all to the hash (dict) of installed packages      if ($action =~ /^Install$/ ){          $installed{$_} = 1 for @packages;      }        # if packages have been removed, remove them all from the hash (dict) of installed packages      if ($action =~ /^(Purge|Remove)$/) {          delete $installed{$_} for @packages;      }  }    # print all installed and not removed packages, in alphabetical order  for my $p ( sort keys %installed ){      print "$p\n";  }  

Usage:

./installed_packages.pl '2015-04-26' /var/log/apt/history.log  

or

perl ./installed_packages.pl '2015-04-26' /var/log/apt/history.log  

For frequent interactive use I'd add validation of script arguments (format of start date), implement -h switch to display short help, and possibly convert start date to named switch (--start).

Good luck!


Solution:2

I took the source code of this response and slightly expanded.

The added value is that you also get purged and removed packages and the output can be filtered with grep.

List installed packages:

./installed_packages.pl '2015-04-28' /var/log/apt/history.log | grep Installed:  

or this for purged or removed:

./installed_packages.pl '2015-04-28' /var/log/apt/history.log | grep -Ei '(Purged|Removed)'  

Source code:

#!/usr/bin/perl    # use as follows:  # ./installed_packages.pl '2015-04-26' /var/log/apt/history.log  # or  # ./installed_packages.pl '2015-04-26 16:08:36' /var/log/apt/history.log    use strict;  use warnings;    # the script expects start date as first argument  my $START_DATE = shift @ARGV;    # hash (dict) to accumulate installed & not removed packages   my %installed;  my %removed;  my %purged;  # flag to mark the beginning of "interesting" period of time  my $start = 0;    # loop over lines from the input file  while (my $line = <>){      # remove end-of-line character       chomp $line;        # skip everything until date becomes greater (or equal) than our x_0      $start ||= $line =~ /^Start-Date: ([^ ]+)/ && $1 ge $START_DATE;      next unless $start;        # we're only interested in lines like       # Install: tupi-data:amd64 (0.2+git02-3build1, automatic), tupi:amd64 (0.2+git02-3build1), libquazip0:amd64 (0.6.2-0ubuntu1, automatic)      # or      # Remove: aptitude-common:amd64 (0.6.8.2-1ubuntu4)      # + separate action (install/remove/purge) from package list      next unless $line =~ /^(Install|Purge|Remove): (.*)$/;       my ($action, $packages_str) = ($1, $2);        # remove versions from the list (they're in parentheses)      # $packages_str =~ s/\(.*?\)//g;        # split single line into array of package names      my @packages = split /\s*,\s*/, $packages_str;      # remove architecture name (comes after ':')      s/:.*// for @packages;        # if packages have been installed, add them all to the hash (dict) of installed packages      if ($action =~ /^Install$/ ){          $installed{$_} = 1 for @packages;      }        # if packages have been removed, add them all to the hash (dict) of installed packages      if ($action =~ /^Remove$/) {          $removed{$_} = 1 for @packages;      }        # if packages have been purged, add them all to the hash (dict) of installed packages      if ($action =~ /^Purge$/) {          $purged{$_} = 1 for @packages;      }  }    # print all installed and not removed packages, in alphabetical order  for my $p ( sort keys %installed ){      print "Installed: $p\n";  }    for my $p ( sort keys %removed ){      print "Removed: $p\n";  }    for my $p ( sort keys %removed ){      print "Purged: $p\n";  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »