#!/usr/bin/env ruby | |
# | |
# CLI tool for locating and removing a Homebrew installation | |
# http://brew.sh/ | |
# | |
# Copyright (C) 2014 Stephen C. Benner | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
# Author: Stephen Benner | |
# https://github.com/SteveBenner | |
# | |
# Contributors: | |
# - @AaronKulick | |
# | |
# NOTE: This script has only been tested and verified to work in OS X 10.9 | |
# | |
require 'optparse' | |
require 'fileutils' | |
require 'open3' | |
$stdout.sync = true | |
# Default options | |
options = { | |
:quiet => false, | |
:verbose => true, | |
:dry_run => false, | |
:force => false, | |
:find_path => false | |
} | |
optparser = OptionParser.new do |opts| | |
opts.banner = 'Homebrew uninstaller' + $/ | |
opts.on('-q', '--quiet', 'Quiet mode - suppress output.') do |setting| | |
options[:quiet] = setting | |
options[:verbose] = false | |
end | |
opts.on('-v', '--verbose', 'Verbose mode - print all operations.') { |setting| options[:verbose] = setting } | |
opts.on('-d', '--dry', 'Dry run - print results, but perform no actual operations.') do |setting| | |
options[:dry_run] = setting | |
end | |
opts.on('-f', '--force', 'Forces removal of files, bypassing prompt. USE WITH CAUTION!') do |setting| | |
options[:force] = setting | |
end | |
opts.on('-p', '--find-path', 'Output homebrew location if found, then exit.') do |setting| | |
options[:find_path] = setting | |
options[:quiet] = true | |
end | |
opts.on_tail('-h', '--help', '--usage', 'Display this message.') { puts opts; exit } | |
opts.on_tail('--version', 'Display script version.') { puts opts.version; exit } | |
end | |
optparser.version = '0.1.2' | |
optparser.summary_width = 16 | |
optparser.parse! | |
$quiet = options[:quiet] # provides access to option value within methods | |
# Files installed into the Homebrew repository | |
BREW_LOCAL_FILES = %w[ | |
.git | |
Cellar | |
Library/brew.rb | |
Library/Homebrew | |
Library/Aliases | |
Library/Formula | |
Library/Contributions | |
Library/LinkedKegs | |
] | |
# Files that Homebrew installs into other system locations | |
BREW_SYSTEM_FILES = %W[ | |
#{ENV['HOME']}/Library/Caches/Homebrew | |
#{ENV['HOME']}/Library/Logs/Homebrew | |
/Library/Caches/Homebrew | |
] | |
$files = [] | |
# This function runs given command in a sub-shell, expecting the output to be the | |
# path of a Homebrew installation. If given a block, it passes the shell output to | |
# the block for processing, using the return value of the block as the new path. | |
# Known Homebrew files are then scanned for and added to the file list. Then the | |
# directory is tested for a Homebrew installation, and the git index is added if | |
# a valid repo is found. The function won't run once a Homebrew installation is | |
# found, but it will accumulate untracked Homebrew files each invocation. | |
# | |
# @param [String] cmd A shell command to run | |
# @param [String] error_msg Message to print if command fails | |
# | |
def locate_brew_path(cmd, error_msg = 'check homebrew installation and PATH.') | |
return if $brew_location # stop testing if we find a valid Homebrew installation | |
puts "Searching for homewbrew installation using '#{cmd}'..." unless $quiet | |
# Run given shell command along with any code passed-in via block | |
path = `#{cmd}`.chomp | |
path = yield(path) if block_given? # pass command output to your own fancy code block | |
begin | |
Dir.chdir(path) do | |
# Search for known Homebrew files and folders, regardless of git presence | |
$files += BREW_LOCAL_FILES.select { |file| File.exist? file }.map {|file| File.expand_path file } | |
$files += Dir.glob('**/{man,bin}/**/brew*') | |
# Test for Homebrew git repository (use popen3 so we can suppress git error output) | |
repo_name = Open3.popen3('git remote -v') do |stdin, stdout, stderr| | |
stderr.close | |
stdout.read | |
end | |
if repo_name =~ /homebrew.git|Homebrew/ | |
$brew_location = path | |
else | |
return | |
end | |
end | |
rescue StandardError # on normal errors, continue program | |
return | |
end | |
end | |
# Attempt to locate homebrew installation using a command and optional code block | |
# for processing the command results. Locating a valid path halts searching. | |
locate_brew_path 'brew --prefix' | |
locate_brew_path('which brew') { |output| File.expand_path('../..', output) } | |
locate_brew_path('command -v brew') { |output| File.expand_path('../..', output) } | |
locate_brew_path 'brew --prefix' do |output| | |
output = output.split($/).first | |
File.expand_path('../..', output) | |
end | |
# Found Homebrew installation | |
if $brew_location | |
if options[:find_path] | |
puts $brew_location | |
exit | |
end | |
unless options[:quiet] | |
puts "Homebrew found at: #{$brew_location}" | |
begin # record kegs and taps for later output | |
brewed = `brew list` | |
tapped = `brew tap` | |
rescue StandardError | |
end | |
end | |
# Collect files indexed by git | |
begin | |
Dir.chdir($brew_location) do | |
# Update file list (use popen3 so we can suppress git error output) | |
Open3.popen3('git checkout master') { |stdin, stdout, stderr| stderr.close } | |
$files += `git ls-files`.split.map {|file| File.expand_path file } | |
end | |
rescue StandardError => e | |
puts e # Report any errors, but continue the script and collect any last files | |
end | |
end | |
# Collect any files Homebrew may have installed throughout our system | |
$files += BREW_SYSTEM_FILES.select { |file| File.exist? file } | |
abort 'Failed to locate any homebrew files!' if $files.empty? | |
# DESTROY! DESTROY! DESTROY! | |
unless options[:force] | |
print "Delete #{$files.count} files? " | |
abort unless gets.rstrip =~ /y|yes/i | |
end | |
rm = | |
if options[:dry_run] | |
lambda { |entry| puts "deleting #{entry}" unless options[:quiet] } | |
else | |
lambda { |entry| FileUtils.rm_rf(entry, :verbose => options[:verbose]) } | |
end | |
puts 'Deleting files...' unless options[:quiet] | |
$files.each(&rm) | |
# Print a list of formulae and kegs that were removed as part of the uninstall process | |
if brewed | |
puts | |
puts 'The following previously installed formulae were removed:' | |
puts brewed | |
end | |
if tapped | |
puts | |
puts 'The following previously tapped kegs were removed:' | |
puts tapped | |
end |
This comment has been minimized.
This comment has been minimized.
Thanks Steve! |
This comment has been minimized.
This comment has been minimized.
Excellent. Thank you. |
This comment has been minimized.
This comment has been minimized.
Worked fine for me, but I also had to resolve one issue unaddressed here... I've tried removing macports, but it still left bad permissions behind. In my case, the problem was this, every time:
So I went to |
This comment has been minimized.
This comment has been minimized.
Instead of relying on |
This comment has been minimized.
This comment has been minimized.
@reactorIO: I’m not sure why the script broke for you; did you modify it before running? Did you use any options/flags? I can’t tell what’s wrong from just the output you pasted, but of course it isn’t supposed to ‘hang’ like that. It seems an |
This comment has been minimized.
This comment has been minimized.
@cauerego Are you saying that after running the unbrew script, there were still homebrew files leftover? If working properly, the script should remove all of the ‘old’ files, and there shouldn’t be any interactions with other software; it should be totally clean so you don’t have to remove anything manually. I intentionally avoid messing with permissions unless truly necessary--my philosophy is to be as unobtrusive as possible, especially with such a tricky subject. There are many ways to configure your system, and depending on how permissions are set up, it may require the use of In the open-source world of Unix/POSIX we’ve gone a long way towards making it easy for software to be interoperable, but unfortunately the freedom and customizability of our systems means it’s still a massive headache much of the time. It takes a lot of knowledge to ‘master’ unix development I think, but if we encourage the propagation of best-practices and focus on constant maintenance and documentation of our systems it will just keep getting easier. For instance, with resources like stackoverflow, it’s incredibly easy for new users (like myself) to discover important conventions and info, such as the fact I am sure that the best philosophy for design of software tools is based on being unopinionated as much as possible, and this is more vital the ‘lower’ something operates in the system. Homebrew captures this with a rare elegance that makes it simple to use and powerful at the same time; that’s why I’m so interested in extending it’s capabilities and supporting it’s usage/adoption. We are going a long way with community work on Homebrew. I don’t contribute directly to the project, (yet) but I do want to work on extending the capabilities of Homebrew at some point soon. Addressing your comment, I hope you can see why Homebrew doesn’t change permissions when installing like you suggest, and I wouldn't change that for an uninstaller tool either. I encourage people to check out this stack exchange thread as it has a lot of very good discussion and information about Homebrew and permissions. I use the command mentioned by the poster on occasion myself to set things straight. |
This comment has been minimized.
This comment has been minimized.
@AaronKulick I’ve never heard of that command before, and after googling a bit it seems to me still quite vague. But I intended the script to be as convenient and invisible to the user as possible, (it should just _work_) so I added your suggestion and attribution. The more code that contributes to a better uninstaller, the better it does it’s job. P.S. I would be interested to know any merits or reasoning behind using the |
This comment has been minimized.
This comment has been minimized.
Hey Steve. I get this when running your initial command ./unbrew.rb: command not found . Any ideas on how I can solve this? And is it harder to uninstall homebrew or macports is harder? |
This comment has been minimized.
This comment has been minimized.
@GrimaceVladimir You'll need to give execute permissions to the script. eg |
This comment has been minimized.
This comment has been minimized.
Hi guysSo I added a new feature (well, two, technically) in which the script will output a list of all formulas and kegs you had installed/tapped, after removing them. I thought it was a pretty clever addition, seeing as the script really does its best to wipe your system of all things Homebrew, possibly leaving you wondering what he hell you had installed previously! I'm in the habit of doing things like The other thing I added was just versioning, and an option to print the script version... I recently discovered that this is a builtin ability of |
This comment has been minimized.
This comment has been minimized.
@GrimaceVladimir I edited my initial comment with more clear instructions for everyone, hope that helps. Also, I haven’t used MacPorts but from what I hear, it’s much more difficult to work with in general. |
This comment has been minimized.
This comment has been minimized.
Works like a charm. Thank you so much for your time. Removing Homebrew can definitely be a pain. |
This comment has been minimized.
This comment has been minimized.
Thanks for helping a playa out. I found this from your AskDifferent post. It helped me debug a problem with one of my packages! |
This comment has been minimized.
This comment has been minimized.
Hi Steve, I ran your script under sudo permissions and had the same problem as @cauerego .Thoughts on the best way to fix it other than permissions alterations? |
This comment has been minimized.
This comment has been minimized.
lol @SteveBenner why not just forego your whole |
This comment has been minimized.
This comment has been minimized.
@ataipale Unfortunately, because the issues you and @cauerego experienced are rooted (haha!) in _permissions_, one of the most convoluted and complicated aspects of Unix, often there is no easy solution except attaining a deeper understanding of how they work, which is why I pointed towards this highly informative stackexchange thread as the ultimate answer to him. I regrettably note that my response to @cauerego became a wall of text that probably came off as rambling… The fact is, this is a very complex and murky topic, which can be seen by how hotly the opinions in the thread are debated. But there you will also find far more than I can provide you, so really check it out. It’s very easy to misunderstand what’s going on otherwise; @cauerego, for example, mentions he set permissions with As a reminder, this script only does ONE thing affecting your system, and that is remove Homebrew. Even when run with
|
This comment has been minimized.
This comment has been minimized.
@sdegutis Such CLI knowledge might seem obvious to us now, but coming from a background of being completely self-taught, I always found huge appreciation in those who went the extra mile to illuminate the science behind it all. Those four particular points are tidbits I consider highly useful and if it helps just one person then I think it’s worth it |
This comment has been minimized.
This comment has been minimized.
I followed the instructions. Ran the script. It worked for me - Mac 10.10.2 Y It ID 3493 files to be removed... I hope they were Homebrew install files only! :) Thanks for a clear and one shot solution to overly debated/questioned prior solution Update: Reinstall worked without any problem.. |
This comment has been minimized.
This comment has been minimized.
Thanks for writing this. When I ran this, however, it didn't actually remove any of the files installed by Homebrew. That is, it removed anything directly Homebrew related (Cellar, the config files) but left everything else that I installed using homebrew (bin, include, share, ...). Is this on purpose? |
This comment has been minimized.
This comment has been minimized.
Thanks for creating this script Steve. The script worked great on my Mac Pro but when I tried to run it on my MacBook Pro, it's hanging right after it starts searching for the homebrew files. These are the 4 lines that I see before it hangs: Searching for homebrew installation using 'brew --prefix'... After a while, I got a message that said Delete 27 files? I said yes and it proceeded to delete those files. When I check out my /usr/local folder, some of the files are still there. When I compare the folder to the one on the Mac Pro, the files remaining are: .gitignore When I ran the script on the Mac Pro, it said it had found over 3,000 files. Should I try to run the script again or is there another solution you can think of? Thanks Steve! Edit: I forgot to mention that I tried running it without sudo first, then ran it with sudo the second time. |
This comment has been minimized.
This comment has been minimized.
Additional information regarding my uninstall issue. I remembered that the only difference in the installation between the mac pro and the macbook pro was xCode. On the mac pro, I had it installed via the command line interface. On the macbook pro, I went through the app store. Not sure if that has any relevance or not though. |
This comment has been minimized.
This comment has been minimized.
Hello. I am very new. I had to re-install my Yosemite OS (iMac) because of a corrupted user profile. Homebrew insists on installing (trying) software to the corrupted user profile. I think I need to remove Homebrew. Looking at the directories in /usr/local/Cellar/, I notice some that appear to be ones I'd like to keep (python, octave, postgresql). If I run your script, do I lose these directories and re-install? How do I know which are the ones that Homebrew installed itself? For reference, permissions are root, group = wheel. Thank you. BSL |
This comment has been minimized.
This comment has been minimized.
@giogadi The directories you've mentioned, ( @jproberts14 I’m not sure how much help I can be to your situation, without more specific constraints to work with. Your Homebrew installation is definitely buggered—I would recommend deleting the entire contents of Bear in mind the script comes with several helpful options designed specifically with troubleshooting in mind. They are all inter-compatible. For instance, if you want to write a list of all the files potentially deleted by the script to a text file, you could run
|
This comment has been minimized.
This comment has been minimized.
Hi Steve, $ sudo ./unbrew.rb I definitely have homebrew installed, so what am/can I do now?? |
This comment has been minimized.
This comment has been minimized.
Hi Steve - thanks for the script. Just FYI I tried this on mac os x 10.6.8 and had the same problem as jproberts14. My guess is that the homebrew installs to different locations on 10.6 and the script doesn't see all of the files (however I am a complete novice so it's entirely just a guess). Your script didn't actually 'hang' as stated by jproberts14 - I was watching the activity in the activity monitor and it said ruby was very busy (with varying levels of cpu and disk activity) presumably looking for files. This took about 5 minutes before coming up with the "Delete 27 files ?" response. Most of the files it found were in the /local/ dir though it missed many others also in there. |
This comment has been minimized.
This comment has been minimized.
Hi Steve, sudo ./unbrew.rb result: when I installed homebrew i quitted by control+C because of network problem. I do not know what should I do now.... @Roboji |
This comment has been minimized.
This comment has been minimized.
I tried Homebrew's uninstall command, which just messed up my installation. I couldn't use any of the packages afterward, nor could I reinstall them. They need to fix that! Your script cleaned out what needed to be cleaned, and made it so I could reinstall Homebrew from scratch. Thanks so much for posting this! |
This comment has been minimized.
This comment has been minimized.
Watch out, this script doesn't stop potentially running services beforehand, something to the effect of: for d in {/Users/`whoami`,}/Library/Launch{Agents,Daemons}/homebrew.mxcl.*.plist; do launchctl unload $d; done |
This comment has been minimized.
This comment has been minimized.
Thank you very much. It works very well. |
This comment has been minimized.
This comment has been minimized.
@SteveBenner, if you have homebrew or homebrew-core already checked out to /usr/local then the script will fail, incorrectly thinking that you have Homebrew installed as oppose to just checked out locally into /usr/local. |
This comment has been minimized.
This comment has been minimized.
@SteveBenner I ran the script but it is stuck at the message "Searching for homewbrew installation using 'brew --prefix'..." for over an hour. Thanks!
This is all I see |
This comment has been minimized.
This comment has been minimized.
Thanks for the effort and continued comments/support - worked flawlessly for me |
This comment has been minimized.
This comment has been minimized.
@SteveBenner I am having the same issues as @cmfrtblynmb728. Any suggestions? No options were given on the command line I just ran ./unbrew.rb. |
This comment has been minimized.
This comment has been minimized.
Likewise, running on 10.10, needed to clear it out, seems to have worked exactly as intended. Much appreciated. |
This comment has been minimized.
This comment has been minimized.
I should have said that I found I had to clear brew out because I still use gfortran from HPC Mac OS X (http://hpc.sourceforge.net) and I needed to reinstall gcc and gfortran (versions 5.1). May not be the best approach these days, so happy to see further comments. Thanks again. |
This comment has been minimized.
This comment has been minimized.
Hello,
Can you please advise what I should do? I also used unbrew.rb with sudo. |
This comment has been minimized.
Instructions:
chmod u+x unbrew.rb
./Users/username/unbrew.rb
, or if the file is in your current working directory:./unbrew.rb
.ln -s <path-to-script> /usr/local/bin/unbrew
to symbolically link it into my executables directory. Now I can just callunbrew
in the shell, like a normal command.sudo
in case there are any permissions irregularities present in your system, which can easily happen. This is just my preference though—it works fine withoutsudo
.