1. Overview

In the world of package management, installing a package often brings with it a large number of dependencies. When we no longer need the original package and remove it, its orphaned dependencies are often left behind.

In this tutorial, we’ll look at how to remove these orphaned packages using various package managers, including apt, dnf, zypper, pacman, and emerge.

2. Our Test Cases

The upcoming installation and removal of packages illustrate the problem of installing numerous dependencies that may become unnecessary after uninstallation. Our choice of packages is purely arbitrary and is for testing purposes only:

# apt, tested on Ubuntu 22.04.3 LTS
$ sudo apt update
$ sudo apt install build-essential
$ sudo apt remove build-essential

# dnf, tested on Fedora 38 Live
$ sudo dnf group install "Development Tools"
$ sudo dnf group remove "Development Tools" --exclude=binutils,bison,elfutils-devel,tbb,zlib-devel

# zypper, tested on openSUSE 20231129 Live
> sudo zypper install -t pattern devel_basis
> sudo zypper remove -t pattern devel_basis

# pacman, tested on Arch Linux 20230617
$ sudo pacman -Syu               # system update, it may be necessary
$ sudo pacman-key --refresh-keys # refresh the PGP keys used by pacman, it may be necessary
$ sudo pacman -S base-devel
$ sudo pacman -R base-devel

# emerge, tested on Gentoo 20230604 Live
$ sudo emerge --sync # synchronize the local copy of the Gentoo ebuild repository with the remote repository
$ sudo emerge gcc make autoconf automake
$ sudo emerge --deselect gcc make autoconf automake

On Fedora, dnf remove without –noautoremove or –exclude also removes dependencies that are no longer needed.

As for Gentoo, we’ve included an example similar to the others only for the sake of completeness, but actually without installing those packages on our test machine. In fact, the live distribution we tested already contains some orphaned packages, as we’ll see later.

3. Delete Orphaned Packages

In general, it’s recommended to always have a backup or snapshot of our machine before removing packages. Unfortunately, we must always bear in mind that the automatic removal of no-longer-used packages can break our Linux installation.

3.1. apt (Debian, Ubuntu, and Derivatives)

It’s quick and easy to remove orphaned dependencies using apt autoremove:

$ sudo apt autoremove
[...]
The following packages will be REMOVED:
  g++ g++-11 libstdc++-11-dev
0 upgraded, 0 newly installed, 3 to remove and 16 not upgraded.
After this operation, 48.8 MB disk space will be freed.
[...]

Fortunately, apt asks for confirmation before proceeding. As a precaution, we should always carefully check which packages it proposes to remove.

3.2. dnf (Fedora, Red Hat Enterprise Linux, and Derivatives)

dnf autoremove gives us an overview of packages that are ready for removal:

$ sudo dnf autoremove
[...]
Dependencies resolved.
================================================================================
 Package                            Arch     Version           Repository  Size
================================================================================
Removing:
 binutils                           x86_64   2.39-16.fc38      @updates    24 M
 binutils-gold                      x86_64   2.39-16.fc38      @updates   2.2 M
 [...]
 zlib-devel                         x86_64   1.2.13-3.fc38     @fedora    139 k

Transaction Summary
================================================================================
Remove  11 Packages
[...]

Similar to apt, dnf also prompts us for confirmation before continuing.

3.3. zypper (openSUSE, SUSE Linux Enterprise, and Derivatives)

zypper provides an easy way to remove unnecessary dependencies only with the –clean-deps option when used in conjunction with the zypper remove command.

Unfortunately, there is no zypper command as simple as apt autoremove or dnf autoremove to remove orphaned dependencies after a package removal performed without –clean-deps.

However, we can work around this problem by creating a shell script that parses the output of zypper packages –unneeded, which gives us the list of unneeded packages:

> sudo zypper packages --unneeded
Loading repository data...
Reading installed packages...
S | Repository              | Name              | Version            | Arch
--+-------------------------+-------------------+--------------------+-------
i | openSUSE-Tumbleweed-Oss | binutils-devel    | 2.41-1.2           | x86_64
i | openSUSE-Tumbleweed-Oss | e2fsprogs-devel   | 1.47.0-2.1         | x86_64
[...]
i | openSUSE-Tumbleweed-Oss | sparse            | 0.6.4+20220627-2.3 | x86_64

So, let’s create the file zypper-clean-deps.sh (authored by gnac), which automates the process of listing unneeded packages, displaying their information, checking for dependencies, and then removing them after asking for confirmation for each one:

#!/bin/sh
zypper packages --unneeded | awk -F'|' 'NR==0 || NR==1 || NR==2 || NR==3 || NR==4 {next} {print $3}' > list
while read p; do zypper info $p && zypper se --requires $p && zypper rm $p; done  < list
rm -rf list

Let’s break it down:

  • zypper packages –unneeded → as seen above, shows information about the package
  • From awk to {print $3}’ → skips the first four lines and print the third field (the package name) of each subsequent line
  • > list → redirects this output to a file named list
  • The while loop then reads each package name from list and performs the following for each package:
    • zypper info $p → shows information about the package
    • zypper se –requires $p → searches for packages that require the given package
    • zypper rm $p → removes the package after prompting for confirmation
  • rm -rf list → removes the list file

Let’s see its execution:

> sudo ./zypper-clean-deps.sh
[...]
Information for package binutils-devel:
---------------------------------------
Repository     : openSUSE-Tumbleweed-Oss
Name           : binutils-devel
[...]
Summary        : GNU binutils (BFD development files)
Description    [...]

[...]

[... List of packages that require binutils-devel ...]

The following package is going to be REMOVED:
  binutils-devel

1 package to remove.
After the operation, 64.8 MiB will be freed.
Continue? [y/n/v/...? shows all options] (y):

A feature for zypper equivalent to apt autoremove has been actively discussed on GitHub since 2017, so it’s likely that it will be added sooner or later.

3.4. pacman (Arch Linux and Derivatives)

We can use pacman -Qdtq to query the package database for orphaned packages:

  • -Q → tells pacman to query the package database
  • -d → lists packages that were installed as dependencies for other packages
  • -t → filters the list to show only orphans
  • -q → shows only package names without extra information

Let’s see what orphaned dependencies it finds in our case:

$ pacman -Qdtq
autoconf
automake
[...]
texinfo

The next step is to use the previous output to remove the listed packages via pacman -Rns $(pacman -Qdtq):

  • $(pacman -Qdtq) → as seen above, lists all orphaned packages
  • -R → removes packages
  • -n → prevents the removal of configuration files
  • -s → removes not only the packages listed but also their dependencies that are not required by other installed packages

Let’s see its execution:

$ sudo pacman -Rns $(pacman -Qdtq)
checking dependencies...
[...]

Packages (21) db-6.2.32-1  db5.3-5.3.28-4  gc-8.2.4-1  guile-3.0.9-1  libis1-0.26-1  libmpc-1.3.1-1
              m4-1.4.19-3  perl-5.38.1-1  autoconf-2.71-4  automake-1.16.5-2  bison-3.8.2-6
              debugedit-5.0-5  fakeroot-1.32.2-1  flex-2.6.4-5  gcc-13.2.1-3  groff-1.23.0-5
              libtool-2.4.7+44+gb9b44533-6  make-4.4.1-2  patch-2.7.6-10  pkgconf-2.0.3-1
              texinfo-7.1-2

Total Removed Size: 365.18 MiB

:: Do you want to remove these packages? [Y/n] _

As in the previous examples, we should always check the suggested list carefully.

3.5. emerge (Gentoo and Derivatives)

In Gentoo Linux, we should run sudo emerge –update –newuse –deep –with-bdeps=y @world, which is a comprehensive way to update the system before removing old or unused packages. Here’s what each part of the command does:

  • –update → updates the packages that are specified in the rest of the command
  • –newuse → if a USE flag has changed, emerge rebuilds the affected packages
  • –deep → ensures a thorough update
  • –with-bdeps=y → ensures that all necessary libraries and tools are present during the update
  • @world → ensures that our entire system and all its applications are up-to-date

After updating, sudo emerge –depclean –pretend is often recommended to clean up unnecessary dependencies:

  • –depclean → removes unused packages
  • –pretend → it’s a way to see what emerge would do without making any changes.

This is what we got on Gentoo Live:

$ sudo emerge --update --newuse --deep --with-bdeps=y @world
[...]

$ sudo emerge --depclean --pretend
[...]
>>> These are the packages that would be unmerged:

 sys-auth/passwdqc
    selected: 2.0.2-r1
   protected: none
     omitted: none

 [...]

Number to remove:     3

$ sudo emerge --depclean
[...]
>>> Unmerging (1 of 3) sys-auth/passwdqc-2.0.2-r1...
>>> Unmerging (2 of 3) sys-kernel/genkernel-4.3.2-r1...
>>> Unmerging (3 of 3) virtual/python-cffi-1...
Packages installed:   1505
Packages in world:    211
Packages in system:   49
Required packages:    1505
Number removed:       3

None of this works unless the system is properly configured. In our case, we had to make some minor changes to the system to fix some errors and install some missing dependencies.

4. Conclusion

In this article, we’ve seen how to manage and remove orphaned packages in various Linux distributions using different package managers.

An important point to keep in mind is that while cleaning up these orphaned packages can save disk space, it can also have unwanted side effects or even break our Linux installation. Therefore, we should always proceed with caution and possibly have a disaster recovery solution.

Comments are closed on this article!