In case anyone else would like to use it, the following is what I used
to uninstall all the files installed by the mac one click installer.
Look how easy it was!
The program produces output while running that identifies each file name
as either a dir or a file. If the file name is a dir, it is skipped. If
the file name is a file, it is deleted. For files that are deleted, the
dir containing the file is examined to determine if it is now empty. If
the dir is empty, it is deleted. Here is some sample output:
/users/me/2testing/dir2 is a dir
—Skipping to next file name.
/users/me/2testing/dir2/aaa.txt is a file
—Deleted file: /users/me/2testing/dir2/aaa.txt
examining dir: /users/me/2testing/dir2
—Dir isn’t empty.
/users/me/2testing/dir2/test1.txt is a file
—Deleted file: /users/me/2testing/dir2/test1.txt
examining dir: /users/me/2testing/dir2
—Dir isn’t empty.
/users/me/2testing/dir2/sub_dir is a dir
—Skipping to next file name.
/users/me/2testing/dir2/sub_dir/bbb.txt is a file
—Deleted file: /users/me/2testing/dir2/sub_dir/bbb.txt
examining dir: /users/me/2testing/dir2/sub_dir
—Dir isn’t empty.
/users/me/2testing/dir2/sub_dir/test2.txt is a file
—Deleted file: /users/me/2testing/dir2/sub_dir/test2.txt
examining dir: /users/me/2testing/dir2/sub_dir
—Deleted dir: /users/me/2testing/dir2/sub_dir
examining dir: /users/me/2testing/dir2
—Deleted dir: /users/me/2testing/dir2
The program also writes every file and directory that it deletes to a
file named:
deleted_files_Mac_One_Click_Installer.txt
so that there is a permanent record of what the program did. The output
to the file looks like this:
Deleted Directories:
/users/me/2testing/dir2/sub_dir
/users/me/2testing/dir2
Deleted Files:
/users/me/2testing/dir2/aaa.txt
/users/me/2testing/dir2/test1.txt
/users/me/2testing/dir2/sub_dir/bbb.txt
/users/me/2testing/dir2/sub_dir/test2.txt
Here is the program (I also wrote some comments after the code):
=begin
If you go here:
/Library/Receipts/
and click on:
Ruby O.-Click Installer for OSX Tiger.pkg
the installer will launch. If you then click on File>Show Files
in the Apple menubar, you will see a list of the files installed
by the installer. To copy all the file names, click anywhere in
the window and hit A and C. You can then paste the
file names into a .txt file by hitting P.
You can also get that list of files here:
/Library/Receipts/Ruby O.-Click Installer for OSX
Tiger.pkg/Contents/Resources$
with this command:
/Library…/Resources$ lsbom -s Ruby\ One-Click\ Installer\ for\ OSX\
Tiger.bom
=end
def get_master_file_and_path_to_remove
puts
puts <<STR
To delete the files under the directory /usr/local, you will most
likely need ‘root permissions’. Therefore, you need to run this
program using the command:
$ sudo ruby this_program_name.rb
password:
If you didn’t run this program using that command, then exit
the program now. Would you like to exit now(‘y’ or ‘n’):
STR
answer = gets.strip
if [‘y’, ‘Y’, ‘yes’].include?(answer)
puts
puts “Program terminated.”
exit(1)
end
puts
puts <<STR
Enter the path to a file that contains the file names you
want to delete(if the path has spaces in it, escape the
spaces with a ‘\’). You will be given the opportunity
to exit the program before any actual deleting takes place:
STR
#File containing all the file names to delete:
delete_list = gets.strip
puts
puts <<STR
Enter the path that should be removed from the front of
the filenames(or hit return for none):
STR
remove_path = gets.strip
if remove_path.length == 0
remove_path = nil
end
#Show examples of new file names:
samples = []
count = 0
fname = nil
IO.foreach(delete_list) do |line|
fname = extract_fname(line, remove_path) #extract_fname() defined
below
if fname
samples << fname
count += 1
break if count > 5
end
end
puts
#Confirm whether these are the file names that should be deleted:
puts <<STR
Do the following look like the names of the files you want to
delete(y or n)?\n
STR
puts samples
answer = gets.strip
puts
if ![‘y’, ‘Y’, ‘yes’].include?(answer)
puts
puts “Program terminated.”
exit(1)
end
puts <<STR
Are you sure you want to delete all the files? If you answer yes,
then this program will scour your hard drive for all the file names
contained in the file you entered. The program will then delete
those files as well as any directories that become empty as a result
of deleting a file. This program will NOT delete the directory
/usr/local or any higher directories.
The names of all the files and directories that were deleted will
be written to a file called:
‘deleted_files_Mac_One_Click_Installer.txt’.
Enter ‘y’(for yes) if you want to begin deleting the files now.
Otherwise enter, ‘n’(for no) if you want to exit the program:
STR
answer = gets.strip
puts
if ![‘y’, ‘Y’, ‘yes’].include?(answer):
puts
puts “Program Terminated”
exit(1)
end
return delete_list, remove_path
end
def extract_fname(line_from_file, path_to_remove=nil)
#remove any leading and trailing whitespace:
fname = line_from_file.strip
if fname.length == 0 #then blank line in file
return nil
elsif not path_to_remove
return fname
else #then chop the specified path off the start of fname
if fname == path_to_remove #
return nil
end
len = path_to_remove.length
if fname[0, len] == path_to_remove #then fname starts with the path
fname = fname[len..-1] #remove leading path from fname
return fname
else #fname doesn't start with the specified path
raise ArgumentError,
"Cannot remove path:\n\t%s from file name:\n\t%s" %
[path_to_remove, fname]
end
end
end
def delete_file(file_name)
#If the file name corresponds to a file, delete the file.
#If the file name is a dir, take no action.
#If the file name doesn’t correspond to an existing file or dir,
#raise a RuntimeError.
if File.directory?(file_name)
printf("%s is a dir\n", file_name)
puts “—Skipping to next file name.”
return false
elsif File.file?(file_name)
printf("%s is a file\n", file_name)
File.delete(file_name)
printf("—Deleted file: %s\n", file_name)
return true
else
raise RuntimeError, “No such file or directory - %s” % file_name
end
end
def delete_empty_dirs(curr_dir, stop_dir)
#Check whether the current directory that used to contain
#the deleted file is empty and therefore should be deleted.
#as well. If the current diretory is deleted, then recursively
#check the parent directories to see if they are now
#empty and need deleting.
#–stop_dir is the furthest up the file hierarchy
#that this method will delete empty dirs.
deleted_dirs = []
while curr_dir != stop_dir
printf(“examining dir: %s\n”, curr_dir)
files_in_dir = Dir.entries(curr_dir)
#Empty dirs on a mac contain the dirs ".", ".." and possibly a file
#called ".DS_Store". A .DS_Store file is created if you ever
#navigated to the dir using Finder. The .DS_Store file contains view
#options, icon position info, etc. Ruby will delete a dir if the dir
#contains only "." and "..", but ruby won't delete a dir if the dir
#contains the file .DS_Store. Hence the following:
empty_dir_on_mac = [".", "..", ".DS_Store"]
extra_files = files_in_dir - empty_dir_on_mac
if extra_files.length == 0 #then dir needs deleting
if files_in_dir.include?(".DS_Store")
full_path = File.join(curr_dir, ".DS_Store")
File.delete(full_path)
end
Dir.delete(curr_dir)
printf("---Deleted dir: %s\n", curr_dir)
deleted_dirs << curr_dir
else
printf("---Dir isn't empty.\n")
break #no need to check parent dirs
end
#Get parent dir for the next loop to examine:
curr_dir = File.dirname(curr_dir)
end
return deleted_dirs
end
def log_results(files_deleted, dirs_deleted)
File.open(‘deleted_files_Mac_One_Click_Installer.txt’, ‘w’) do |file|
file.puts(“Deleted Directories:”)
file.puts(dirs_deleted)
file.puts
file.puts("Deleted Files:")
file.puts(files_deleted)
end
end
#------MAIN PROGRAM-----------
delete_list, path_to_remove = get_master_file_and_path_to_remove()
deleted_files = []
deleted_dirs = []
IO.foreach(delete_list) do |a_line|
#Extract a file name from the line:
fname = extract_fname(a_line, path_to_remove)
next if !fname
#If fname is the name of a file, delete it:
if delete_file(fname)
deleted_files << fname
else #then fname is a dir
next #A dir doesn’t become empty unless you delete a file contained
#therein, so skip the code below which checks for empty dirs.
end
#Delete any directories that are now empty as the result
#of deleting a file:
top_dir = ‘/users/autie/2testing’ #don’t check directories above this
one
dir_name = File.dirname(fname)
deleted = delete_empty_dirs(dir_name, top_dir)
deleted_dirs.concat(deleted)
end
#Write the names of all the deleted files and dirs
#to a file:
log_results(deleted_files, deleted_dirs)
===============
===============
Comments on testing
For testing, I used this hierarchy:
/
–users
-----me
-------2testing
-----------dir2
---------------aaa.txt
---------------test1.txt
---------------sub_dir
-------------------test2.txt
-------------------bbb.txt
This was my list of files to delete:
./users/me/2testing/dir2
./users/me/2testing/dir2/aaa.txt
./users/me/2testing/dir2/test1.txt
./users/me/2testing/dir2/sub_dir
./users/me/2testing/dir2/sub_dir/bbb.txt
./users/me/2testing/dir2/sub_dir/test2.txt
During testing, I used the directory /users/me/2testing as the top
directory in the code (instead of /usr/local). After running the
program and entering the file name with the files to delete and ‘.’ as
the path to remove, I was left with this hierarchy:
/
–me
----2testing
After getting that to work correctly, I changed the top directory in the
code to /usr/local, and then I ran the program for real. When prompted,
I entered a file name containing all the files that the mac one click
installer installed, and I entered ‘.’ as the path to remove.
After the program finished deleting all the files, the pre-installed
ruby, which is version 1.8.2 for me, worked without me doing anything
else, and ruby tk started working again.