How to fully uninstall apps in macOS just using bash

Free but powerful solutions to uninstall any application

Introduction

When you install a new application on your mac, the setup will throw a lot of files through your system directories. Even after the installation, many apps will continue to create config and helper files in different directories.

Since MacAppStore came, lots of applications are now available on the MacAppStore, and uninstalling them is just a push of a button, but still, there are tons of applications still out there that are not available on the MacAppStore for different reasons—like requiring access that is not permitted by the MacAppStore guidelines.

Many application like CleanMyMac has come to solve the issue of uninstalling outside MacAppStore applications and taking care of completely cleaning their configs, helper, logger and etc files. Those applications are expensive for such a simple task and also not all of them are that good at finding extra files. In this blog post, I am going to show you how I used a single-line bash script to fully uninstall any application that I don’t like to have anymore.

Understanding macOS directories

macOS uses specific directories to store user, system, and application configurations. It is crucial to understand these libraries as it will help us to differentiate the application files from the other files.

macOS uses plist files as configuration files. So, it is the most probable file type you will see any application creates. Also, apple likes to store these configurations under two directories. The first directory that is holds applications and system-related stuff is /Library this folder holds files that are owned by the root and are available for all the users. In contrast, the ~/Library holds user-level files.

The bash commands

To begin with, we need to understand three commands in bash first, and then by the power of bash pipe we will put them together to create our own easy uninstaller.

1. The mdfind command

The first command to understand it is mdfind. This command is responsible for searching for files through the whole system. By passing the option command -name we can look for a regex pattern or an exact word in files names and paths.

Here is an example of running the mdfind command to find all files that have “iterm2” in their name:

mdfind -name iterm2

Here is an output example:

/Users/kiarash/Library/Application Support/iTerm2/iterm2-daemon-1.socket.lock
/Users/kiarash/Library/HTTPStorages/com.googlecode.iterm2
/Users/kiarash/Library/Application Support/iTerm2
/usr/local/Caskroom/iterm2
/usr/local/Cellar/ncurses/6.3/share/terminfo/69/iterm2-direct
/usr/local/Cellar/ncurses/6.3/share/terminfo/69/iTerm2.app
/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask/Casks/iterm2.rb

2. The vipe command

As I mentioned before many uninstalling applications aren’t able to fully clean the extra files because they only look for specific files in specific directories that I mentioned earlier. What I like to do instead is to use mdfind to search for any related files and then use an editor like neovim to list all the candidate files and then edit the list of the candidates and return it back to the bash script to be removed.

💡Note 1: If you haven't used neovim but vim instead, don't worry! neovim is just the community version for vim.

💡Note 2: If you haven't used either neovim or vim check out this tutorial or use nano instead.

To achieve that goal I used vipe. This command basically takes the output of the first command, passes it to the default editor–which here is neovim–and then after saving and quitting from the default editor, it will pass the edited and saved list to the second command.

Before using the vipe command, we need to install it via brew as it is not installed by default in macOS. To install vipe we need to install a formula named moreutils which contains vipe.

brew install moreutils

Now you can use the pattern below to use the pass, edit, and pass process between two commands:

command1 | vipe | command2

3. The xargs command

Let’s say we successfully listed all the related files to the application which we wish to be removed completely. It is obvious now that we need rm command to delete them, but each file is on a separate line. Also, the rm does not accept the pipe output as argument. To address this issue we will use the xargs command. This command can take a pipe output and run a bash command with that. Plus, the -L option will split the lines and loop through them i.e. it will rm command separately with each line. The script below demonstrates how we can remove a list of files from a text file as a source:

cat source.txt | xargs -L 1 -I {} rm -r {}

4. Put it all together

Now that we learn about each command, it's time to combine them together and make a script out of them. Save the script below in the unapp.sh file.

#!/bin/zsh
mdfind -name $1 | vipe | xargs -L 1 -I {} rm -rf {}

Make the script executable by:

sudo chmod +x unapp.sh

No we can uninstall any app fully using the command below:

./unapp.sh iTerm2

References