You have a Debian, Ubuntu or similar installation, and your /var
partition keeps getting full when you upgrade. You check /var/cache/apt/archives
and find it full of the usual mix of current and old versions of downloaded packages. Somehow, they haven't been deleted after installation, or you keep downloading them but not installing them. You now need a quick and clever way of cleaning up this mess, so only the latest version of each package remains.
Solution
Here's an appropriate bash invocation:
find /var/cache/apt/archives/ -name '*deb' |
perl -ne 'print "$1\n" if /([^\/_]+)_/'|
sort -u |
while read a; do
find /var/cache/apt/archives/ -name "${a}_*" |
sort -r | tail -n+1 | xargs -rp sudo rm -v;
done
For each package name, this will delete all but the latest .deb
package. Obviously, if there's only one version of a package, it's not deleted. You will be asked to confirm each deletion.
sudo
from the second line. On Ubuntu, sudo
is already set up for you, and you should use it. On Debian, you need to install and set it up yourself.Discussion
Debian package names can't contain an underscore (_
). Everything that comes after the underscore in a .deb
filename is version (and platform) information. The first three lines of the script locate all packages and get their unique name stems. By using find
rather than using something like ls /var/cache/apt/archives/*.deb
, we avoid failure in case there are too many packages for the command line1. It's also a very bad idea to parse ls
output.
The second line finds everything between the last /
and first _
of each line and prints that out. This is the package name.
The third line collects all of the package names, sorts them and prints out unique names so we don't duplicate any effort.
Then, the while
…done
loop reads each of these stems, locates all the archived files matching the stem, sorts them in reverse order (i.e. most recent package first) and deletes all but the first one. It does this by running sudo rm -v
via xargs
The -p
option prompts before executing the command and -r
doesn't execute if the argument list is empty (i.e. nothing to delete).
find
. Over to you!