On a debian linux box the directory /var/cache/apt/archives gradually fills up with every .deb file you have ever installed or have ever downloaded with the option of installing. If a file corresponds to your currently installed version or is currently the most advanced version of that package you have available then you want to keep it, otherwise it’s redundant and may as well be deleted.

For example, let’s say I have 12 versions of bash sitting in that directory; the first 8 are previous versions, the 9th is the installed version, and the last 3 are versions I have downloaded but not gotten to the point of actually installing. In that case I want to keep the 9th and 12th files and delete the other 10.

Here is a perl script that will do exactly that. You could have a nightly script that did

apt-get update
apt-get upgrade --download-only -qq

then ran the following clean up script, then emailed you the list of packages having upgrades available.

#!/usr/bin/perl

use strict;
use warnings;

use Dpkg::Version qw(version_compare);

my %installed = ();

eval {
    my $pid = open(STATUS, '/usr/bin/dpkg-query -l | /bin/grep ^i |')
        or die 'Failed to get package status feed';
    while (defined($_ = )) {
        chomp;
        if (/^\w\w\s+(\S+)\s+(\S+)\s/) {
            $installed{$1} = $2;
        }
        else {
            die 'Unrecognised package status line';
        }
    }
    close(STATUS);
};
if ($@) {
    die "Failed to build list of installed versions\n". $@;
}

my %candidate = ( %installed );

eval {
    my $archive_dir = '/var/cache/apt/archives';
    opendir(AVAIL, $archive_dir)
        or die 'Failed to read archive dir';
    while (defined(my $deb = readdir(AVAIL))) {
        chomp $deb;
        if ($deb =~ /^([^_]+)_([^_]+)_/) {
            my ($p, $v) = ($1, $2);
            $v =~ s/%3a/:/g;
            if (exists $candidate{$p}) {
                my $cmp = version_compare($candidate{$p}, $v);
                if ($cmp  0) {
                    # Found a non-maximal version
                    unlink $deb
                        unless $installed{$p} && $installed{$p} eq $v;
                }
            }
            else {
                $candidate{$p} = $v;
            }
        }
        else {
            warn "Ignoring unrecognised file ($deb)";
        }
    }
    closedir(AVAIL);
};
if ($@) {
    die "Failed to build list of available versions\n". $@;
}

__END__
Advertisements