Is there a simple way to select a range of packages (especially kernel related packages) for installation or removal with apt (or another tool) ?

Currently, I am trying to remove a range of old kernels with apt remove linux-\*-4.4.0-{40..80}-\*.

This correctly selects the packages I want to remove, but the process is immediately interrupted by errors of the form E: Couldn't find any package by glob 'linux-*-4.4.0-65-*'.

Indeed, there is no package corresponding to this regexp, but I am very surprised by the fact that this leads to an error instead of a warning. After all, removing an empty set of packages is trivial !


This can be done using command substitution. For example:

apt-get remove $(dpkg -l 'linux-*' | awk '/-4.4.0-([4-7][0-9]|80)-/ { print $2}')

Or with dlocate if you have it installed:

apt-get remove $(dlocate -k | grep -E -- '-4.4.0-([4-7][0-9]|80)-') 

Unlike any solution involving xargs, command substitution does not change apt-get's stdin file-descriptor, so apt-get can receive input normally (e.g. answers to debconf questions). xargs gets its own input from stdin, so should not be used with interactive programs, i.e. programs that may want input from stdin.

To use apt-get with xargs, you first have to make sure it will not ask any questions, e.g.:

export DEBIAN_FRONTEND=noninteractive
dlocate -k | grep -- -4.4.0- | xargs apt-get remove -y

Note about dlocate: The -k option lists all installed kernel and dkms related packages, one per line (and -K does the same, but in verbose dpkg -L format). I added the -k option to dlocate to enable exactly this kind of usage, but until now it never occurred to me that there should be an optional regexp argument after the -k, even though that is completely obvious - I've always just used it with grep.

The next version of dlocate (i.e. >= 1.08) will support dlocate -k '-4.4.0-' with no need to pipe the output through grep.

  • apt list linux-\*-4.4.0-{40..80}-\* | cut -d / -f 1 gives a correct list of packages, but using it with command substitution leads to a warning from it apt does not have a stable CLI interface. Use with caution in scripts., and indeed, the whole apt-get remove $(apt list linux-\*-4.4.0-{40..80}-\* | cut -d / -f 1) fails because intermediate output by apt is parsed by apt-get. apt-get does not have a list operation.
    – ysalmon
    Aug 2 '17 at 12:07
  • dlocate -k | grep -F -- -4.4.0- gives the list of all kernel packages, not only the ones in range 40..80.
    – ysalmon
    Aug 2 '17 at 12:08
  • so write a regexp for grep that matches. mine was only a simple example. dlocate -k | grep -E -- '-4.4.0-.*([4-7][0-9]|80)-'
    – cas
    Aug 2 '17 at 12:25
  • removed apt-list example and replaced it with a dpkg -l example. seems apt-list won't work as required with either command-substitution or xargs.
    – cas
    Aug 2 '17 at 12:31

Something like apt list linux-\*-4.4.0-{40..80}-\*|awk -F '/' '{print $1}' |xargs apt remove should work I would think.

  • using apt-get with xargs can have problems if apt-get needs to ask any questions. generally better use command-substitution, e.g. apt-get remove $(apt list linux-\*-4.4.0-{40..80}-\* | cut -d / -f 1)
    – cas
    Aug 1 '17 at 12:42
  • btw, i generally do something like apt-get purge $(dlocate -k | grep -E '-4\.(9|10)\.') to get rid of old kernel image and header packages.
    – cas
    Aug 1 '17 at 12:45
  • @cas your comments put together would constitute an interesting answer IMO. Aug 1 '17 at 13:39

get the list of installed packages (linux-image):

dpkg --list | grep  linux-image | awk '{print $2}' > file

Sort/edit your file , keep only the linux-image to be removed , then run:

file=$(cat file)
echo "$file"
apt remove $file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.