When you remove a package (such as sudo apt remove php5.5-cgi), all files added by the package will be deleted except for user configuration files that were modified. When you purge a package (such as sudo apt purge php5.5-cgi), all the package files, including modified configuration files, are deleted. After a few years, your Ubuntu installation may start to accumulate old packages that were removed but not purged. Fortunately, it is easy to find those unpurged packages and purge them.

The dpkg command can provide us with a list of removed, unpurged packages:

[chris@home ~]$ dpkg --list | grep ^rc
rc  php5.5-cgi       5.5.38-4+deb.sury.org~xenial+1  amd64  server-side, HTML-embedded scripting language (CGI binary)
rc  php5.5-cli       5.5.38-4+deb.sury.org~xenial+1  amd64  command-line interpreter for the PHP scripting language
rc  php5.5-common    5.5.38-4+deb.sury.org~xenial+1  amd64  documentation, examples and common module for PHP
rc  php5.5-json      5.5.38-4+deb.sury.org~xenial+1  amd64  JSON module for PHP
rc  php5.5-opcache   5.5.38-4+deb.sury.org~xenial+1  amd64  Zend OpCache module for PHP
rc  php5.5-readline  5.5.38-4+deb.sury.org~xenial+1  amd64  readline module for PHP
[chris@home ~]$ 

The dpkg command is Ubuntu’s package manager. The apt, aptitude, apt-get, and other apt-* commands are simply wrappers around dpkg. Calling dpkg --list creates a listing of all the packages on the system. Filtering the output by piping it through grep ^rc results in only showing the removed but unpurged packages (the ^rc pattern means that only lines beginning with “rc” should be output). The “r” in “rc” means that the package was removed while the “c” means that the config files remain.

We can use awk to get a listing of just the package names:

[chris@home ~]$ dpkg --list | grep ^rc | awk '{ print $2; }'
[chris@home ~]$ 

The awk command processes and manipulates string. By default, when awk reads each line of input, it will separate the input into a series of fields separated by runs of whitespace. You can refer to a specific field by using $NUMBER. In this instance, we tell it to print the second field by using { print $2; }. This results in a listing of just the package names.

Now that we have our names, we just need to purge each one:

[chris@home ~]$ sudo apt purge `dpkg --list | grep ^rc | awk '{ print $2; }'`
[sudo] password for chris:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  php5.5-cgi* php5.5-cli* php5.5-common* php5.5-json* php5.5-opcache* php5.5-readline*
0 upgraded, 0 newly installed, 6 to remove and 0 not upgraded.
After this operation, 0 B of additional disk space will be used.
Do you want to continue? [Y/n]
(Reading database ... 432300 files and directories currently installed.)
Removing php5.5-cgi (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-cgi (5.5.38-4+deb.sury.org~xenial+1) ...
dpkg: warning: while removing php5.5-cgi, directory '/etc/php/5.5/cgi/conf.d' not empty so not removed
Removing php5.5-cli (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-cli (5.5.38-4+deb.sury.org~xenial+1) ...
dpkg: warning: while removing php5.5-cli, directory '/etc/php/5.5/cli/conf.d' not empty so not removed
Removing php5.5-common (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-common (5.5.38-4+deb.sury.org~xenial+1) ...
dpkg: warning: while removing php5.5-common, directory '/etc/php/5.5/mods-available' not empty so not removed
Removing php5.5-json (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-json (5.5.38-4+deb.sury.org~xenial+1) ...
Removing php5.5-opcache (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-opcache (5.5.38-4+deb.sury.org~xenial+1) ...
Removing php5.5-readline (5.5.38-4+deb.sury.org~xenial+1) ...
Purging configuration files for php5.5-readline (5.5.38-4+deb.sury.org~xenial+1) ...
[gaarai@samus ~/src/lynis]$ 

By surrounding command to get the listing of packages with backticks (`), the output of that entire command can be used as an argument for another command. In this case, the output is used to tell the apt command to purge the packages.

Note the warnings stating that specific directories were not removed. I checked each of these directories, found that there were empty, and removed them manually.

Did I help you? Send me a tip.