How to fully uninstall apps in macOS just using bash
Free but powerful solutions to uninstall any application
Photo by Boitumelo Phetla on Unsplash
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