6

I have a github action with a step for freeing space and it has a apt purge command followed by hundreds of packages. But if one package is not available, the all process fails

If you apt purge or remove a huge list of several packages at once, how to force the purge of existing installed packages?

Example:

sudo apt purge pack1 pack2 pack3 -y

if pack1 and pack2 exist but pack3 does not exists, the process fails

E: Unable to locate package 'pack3'

and pack1 and pack2 are not purged.

How to force removal of pack1 and pack2 even if one of the remaining doesn't exist?

2 Answers2

5

To the point

Needles to say that:

  1. Purging hundreds of installed packages at once is a bad idea regardless of the reason for that.

  2. Using APT's option -y to automatically answer yes, is even a worse idea.

You probably know that, but I had to note it ... On to your question:

AFAIK APT can't do that ... APT does more than the basic actions of just attempt to install, remove, purge ... etc. ... It resolves dependencies, avoids and warns about conflicts, substitutes some removed packages ... etc. ... Thus it has to parse/check all passed packages against its cached available packages database before it begins committing any user specified action on them.

Therefore, your best bet in that situation is to pass those packages one at a time to APT using xargs like:

echo "pack1 pack2 pack3" | xargs -n 1 apt purge

or using a shell loop like:

for p in "pack1" "pack2" "pack3"
  do
    apt purge "$p"
    done

or similar solutions.

On the other hand, if using APT is not a must for you, then dpkg should do the job without exiting on such packages "Unable to locate packages" and can be used like so:

dpkg --purge pack1 pack2 pack3

Around the point

Demonstration:

$ apt -s purge -y vlc golang
NOTE: This is only a simulation!
      apt needs root privileges for real execution.
      Keep also in mind that locking is deactivated,
      so don't depend on the relevance to the real current situation!
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package 'golang' is not installed, so not removed
The following packages will be REMOVED:
  vlc*
0 to upgrade, 0 to newly install, 1 to remove and 5 not to upgrade.
Purg vlc [3.0.16-1build7]

Notice the three steps before committing the purge action:

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done

These are self explanatory and although the package golang is not installed:

Package 'golang' is not installed, ...

But, APT could locate it in its cached packages list and thus could take a decision regarding it:

... so not removed 

and:

The following packages will be REMOVED:
  vlc*
...

That is normal and APT will carry on removing the installed package/s

But in case of a package that APT can't locate in its cached packages lists:

$ apt -s purge -y vlc non-locatable-package
NOTE: This is only a simulation!
      apt needs root privileges for real execution.
      Keep also in mind that locking is deactivated,
      so don't depend on the relevance to the real current situation!
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package non-locatable-package

APT can't take the decision and thus exits after printing an error:

E: Unable to locate package non-locatable-package

Important notice:

As seen in the demonstration above, APT checks its cached packages lists obtained via the update action and therefore, an up to date packages list/s is vital to correct functionality of APT and doing purge/remove or even install actions with an outdated packages list/s might result in an unexpected result removing unintended packages ... See for example apt-get install unexpectedly removed Firefox ... Therefore, make sure the packages list/s are up to date by running:

sudo apt update

first.

Raffa
  • 34,963
0

The approach I would recommend would be doing a ‘join’ between the list of packages you want removed and the list of packages currently installed. Doing a join is a bit clunky in the shell, but there's a comm command specifically designed for it, as long as both input files are already sorted.

Here I allow arbitrary spaces in the $doomed_packages variable to allow pretty formatting. They are removed by the tr and grep that are applied before I sort the names:

#!/bin/bash

doomed_packages=" command-not-found python3-commandnotfound nfs-common nfs-kernel-server portmap notify-osd pm-utils ubuntu-advantage-desktop-daemon aspell-en " doomed_packages="$(comm -12
<(echo $doomed_packages | tr ' ' '\n' | grep . | sort)
<(dpkg-query --show --showformat='${Package}\n')
)" if [ -n "$doomed_packages" ] then sudo apt purge "$doomed_packages" fi

Happily, dpkg-query sorts its output, so we can avoid running sort again. (Well, probably; what if its default sorting algorithm is different than that of sort? You could throw in | sort behind dpkg-query if that worries you!)