bytelyst-devops-tools/cleanup.sh

661 lines
24 KiB
Bash
Executable File

#!/bin/bash
# ==========================================
# System Cleanup Script for macOS
# ==========================================
#
# This script helps clean up various caches and temporary files to free up disk space.
# Use with caution - while this script tries to be safe, it's always good to have backups.
#
# Features:
# - Clean development tool caches (Homebrew, npm, pip, etc.)
# - Clean browser caches (Chrome, Firefox, Safari)
# - Clean application caches
# - Clean system caches and logs
# - Interactive menu to choose what to clean
# - Size reporting before and after cleaning
#
# Author: Saravana
# Created: 2025-05-21
# ==========================================
# ==========================================
# Color Definitions
# ==========================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# ==========================================
# Helper Functions
# ==========================================
# Print with color
print_header() {
echo -e "\n${CYAN}===== $1 =====${NC}\n"
}
print_info() {
echo -e "${BLUE}INFO: $1${NC}"
}
print_warning() {
echo -e "${YELLOW}WARNING: $1${NC}"
}
print_error() {
echo -e "${RED}ERROR: $1${NC}"
}
print_success() {
echo -e "${GREEN}SUCCESS: $1${NC}"
}
print_size() {
path="$1"
if [ -e "$path" ]; then
size=$(du -sh "$path" 2>/dev/null | cut -f1)
echo -e "${PURPLE}Size of $path: $size${NC}"
else
echo -e "${PURPLE}$path does not exist${NC}"
fi
}
# Check if a directory exists and has content
check_directory() {
local dir="$1"
if [ -d "$dir" ] && [ "$(ls -A "$dir" 2>/dev/null)" ]; then
return 0
else
return 1
fi
}
# Get directory size in human-readable format
get_dir_size() {
local dir="$1"
if [ -d "$dir" ]; then
du -sh "$dir" 2>/dev/null | cut -f1
else
echo "0B"
fi
}
# Get directory size in bytes
get_dir_size_bytes() {
local dir="$1"
if [ -d "$dir" ]; then
du -s "$dir" 2>/dev/null | cut -f1
else
echo "0"
fi
}
# Get free disk space
get_free_space() {
df -h . | awk 'NR==2 {print $4}'
}
# Confirm action
confirm() {
local prompt="$1"
local default="$2"
if [ "$default" = "y" ]; then
local prompt_text="${prompt} [Y/n] "
else
local prompt_text="${prompt} [y/N] "
fi
read -p "$prompt_text" response
if [ -z "$response" ]; then
response="$default"
fi
if [[ "$response" =~ ^[Yy]$ ]]; then
return 0
else
return 1
fi
}
# ==========================================
# Cleanup Functions
# ==========================================
# Clean Development Tool Caches
clean_dev_caches() {
print_header "Cleaning Development Tool Caches"
# Homebrew
if check_directory "$HOME/homebrew/Caches" || check_directory "$HOME/Library/Caches/Homebrew"; then
print_info "Cleaning Homebrew caches..."
before_size=$(get_dir_size "$HOME/Library/Caches/Homebrew")
if confirm "Run 'brew cleanup' to remove old versions and downloads? This will free up space but require re-downloading if needed again." "y"; then
brew cleanup -s
rm -rf "$HOME/Library/Caches/Homebrew"/*
print_success "Homebrew cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/Homebrew")"
fi
fi
# Node/npm
if check_directory "$HOME/.npm"; then
print_info "Cleaning npm cache..."
before_size=$(get_dir_size "$HOME/.npm")
if confirm "Clean npm cache?" "y"; then
npm cache clean --force
print_success "npm cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/.npm")"
fi
fi
# pnpm
if check_directory "$HOME/.pnpm-store" || check_directory "$HOME/Library/Caches/pnpm"; then
print_info "Cleaning pnpm cache..."
before_size=$(get_dir_size "$HOME/.pnpm-store")
before_size2=$(get_dir_size "$HOME/Library/Caches/pnpm")
if confirm "Clean pnpm cache?" "y"; then
if command -v pnpm &>/dev/null; then
pnpm store prune
fi
rm -rf "$HOME/Library/Caches/pnpm"/*
print_success "pnpm cache cleaned. Before: $before_size + $before_size2, After: $(get_dir_size "$HOME/.pnpm-store") + $(get_dir_size "$HOME/Library/Caches/pnpm")"
fi
fi
# Yarn
if check_directory "$HOME/.yarn/cache"; then
print_info "Cleaning Yarn cache..."
before_size=$(get_dir_size "$HOME/.yarn/cache")
if confirm "Clean Yarn cache?" "y"; then
if command -v yarn &>/dev/null; then
yarn cache clean
fi
print_success "Yarn cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/.yarn/cache")"
fi
fi
# pip
if check_directory "$HOME/Library/Caches/pip"; then
print_info "Cleaning pip cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/pip")
if confirm "Clean pip cache?" "y"; then
if command -v pip &>/dev/null; then
pip cache purge
fi
rm -rf "$HOME/Library/Caches/pip"/*
print_success "pip cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/pip")"
fi
fi
# Cypress
if check_directory "$HOME/Library/Caches/Cypress"; then
print_info "Cleaning Cypress cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/Cypress")
if confirm "Clean Cypress cache? This includes browser binaries that will need to be re-downloaded." "y"; then
rm -rf "$HOME/Library/Caches/Cypress"/*
print_success "Cypress cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/Cypress")"
fi
fi
# Playwright
if check_directory "$HOME/Library/Caches/ms-playwright"; then
print_info "Cleaning Playwright browsers cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/ms-playwright")
if confirm "Clean Playwright browsers cache? These will need to be re-downloaded if used again." "y"; then
rm -rf "$HOME/Library/Caches/ms-playwright"/*
print_success "Playwright cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/ms-playwright")"
fi
fi
# Gradle
if check_directory "$HOME/.gradle/caches"; then
print_info "Cleaning Gradle cache..."
before_size=$(get_dir_size "$HOME/.gradle/caches")
if confirm "Clean Gradle cache?" "y"; then
rm -rf "$HOME/.gradle/caches"/*
print_success "Gradle cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/.gradle/caches")"
fi
fi
# CocoaPods
if check_directory "$HOME/Library/Caches/CocoaPods"; then
print_info "Cleaning CocoaPods cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/CocoaPods")
if confirm "Clean CocoaPods cache?" "y"; then
rm -rf "$HOME/Library/Caches/CocoaPods"/*
print_success "CocoaPods cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/CocoaPods")"
fi
fi
# Go modules
if check_directory "$HOME/go/pkg/mod"; then
print_info "Cleaning Go module cache..."
before_size=$(get_dir_size "$HOME/go/pkg/mod")
if confirm "Clean Go module cache? These will be re-downloaded when needed." "y"; then
if command -v go &>/dev/null; then
go clean -modcache
fi
print_success "Go module cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/go/pkg/mod")"
fi
fi
}
# Clean Browser Caches
clean_browser_caches() {
print_header "Cleaning Browser Caches"
# Check and close browsers first
for browser in "Firefox" "Google Chrome" "Safari" "Microsoft Edge" "Brave Browser"; do
if pgrep "$browser" >/dev/null; then
print_warning "$browser is currently running."
if confirm "Would you like to close $browser before cleaning its cache?" "y"; then
osascript -e "tell application \"$browser\" to quit"
sleep 2
else
print_warning "Skipping $browser cleanup to avoid potential issues."
continue
fi
fi
case "$browser" in
"Firefox")
if check_directory "$HOME/Library/Caches/Firefox"; then
print_info "Cleaning Firefox cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/Firefox")
if confirm "Clean Firefox cache?" "y"; then
rm -rf "$HOME/Library/Caches/Firefox"/*
print_success "Firefox cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/Firefox")"
fi
fi
;;
"Google Chrome")
if check_directory "$HOME/Library/Caches/Google/Chrome"; then
print_info "Cleaning Chrome cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/Google/Chrome")
if confirm "Clean Chrome cache?" "y"; then
rm -rf "$HOME/Library/Caches/Google/Chrome"/*
print_success "Chrome cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/Google/Chrome")"
fi
fi
;;
"Safari")
if check_directory "$HOME/Library/Caches/com.apple.Safari"; then
print_info "Cleaning Safari cache..."
if confirm "Clean Safari cache?" "y"; then
print_warning "Safari caches require administrator privileges."
if confirm "Run with sudo (will prompt for password)?" "n"; then
sudo rm -rf "$HOME/Library/Caches/com.apple.Safari"/*
print_success "Safari cache cleaned."
fi
fi
fi
;;
"Microsoft Edge")
if check_directory "$HOME/Library/Caches/Microsoft Edge"; then
print_info "Cleaning Microsoft Edge cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/Microsoft Edge")
if confirm "Clean Microsoft Edge cache?" "y"; then
rm -rf "$HOME/Library/Caches/Microsoft Edge"/*
print_success "Microsoft Edge cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/Microsoft Edge")"
fi
fi
;;
"Brave Browser")
if check_directory "$HOME/Library/Caches/BraveSoftware/Brave-Browser"; then
print_info "Cleaning Brave Browser cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/BraveSoftware/Brave-Browser")
if confirm "Clean Brave Browser cache?" "y"; then
rm -rf "$HOME/Library/Caches/BraveSoftware/Brave-Browser"/*
print_success "Brave Browser cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/BraveSoftware/Brave-Browser")"
fi
fi
;;
esac
done
}
# Clean Application Caches
clean_app_caches() {
print_header "Cleaning Application Caches"
# Check for common application caches
cache_dir="$HOME/Library/Caches"
# List large application caches
print_info "Scanning for large application caches..."
# Get top 10 largest cache directories
large_caches=$(find "$cache_dir" -type d -maxdepth 1 2>/dev/null | xargs du -sh 2>/dev/null | sort -hr | head -n 10)
echo -e "${YELLOW}Largest application caches:${NC}"
echo "$large_caches"
echo
# Spotify
if check_directory "$HOME/Library/Caches/com.spotify.client"; then
print_info "Cleaning Spotify cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/com.spotify.client")
if confirm "Clean Spotify cache? This may remove offline songs." "n"; then
rm -rf "$HOME/Library/Caches/com.spotify.client"/*
print_success "Spotify cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/com.spotify.client")"
fi
fi
# Slack
if check_directory "$HOME/Library/Caches/com.tinyspeck.slackmacgap"; then
print_info "Cleaning Slack cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/com.tinyspeck.slackmacgap")
if confirm "Clean Slack cache?" "y"; then
rm -rf "$HOME/Library/Caches/com.tinyspeck.slackmacgap"/*
print_success "Slack cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/com.tinyspeck.slackmacgap")"
fi
fi
# Visual Studio Code
if check_directory "$HOME/Library/Caches/com.microsoft.VSCode"; then
print_info "Cleaning VS Code cache..."
before_size=$(get_dir_size "$HOME/Library/Caches/com.microsoft.VSCode")
if confirm "Clean VS Code cache?" "y"; then
rm -rf "$HOME/Library/Caches/com.microsoft.VSCode"/*
print_success "VS Code cache cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches/com.microsoft.VSCode")"
fi
fi
# Docker
if check_directory "$HOME/Library/Containers/com.docker.docker"; then
print_info "Found Docker containers cache..."
before_size=$(get_dir_size "$HOME/Library/Containers/com.docker.docker")
if confirm "Would you like to see Docker disk usage? (This will run 'docker system df')" "y"; then
if command -v docker &>/dev/null; then
docker system df
if confirm "Clean unused Docker data? (This will run 'docker system prune')" "n"; then
docker system prune -f
print_success "Docker unused data cleaned."
fi
else
print_error "Docker command not found."
fi
fi
fi
# Clean other large caches
if confirm "Would you like to see and clean other large application caches?" "y"; then
print_info "Select cache directories to clean (enter numbers separated by space):"
# Get all cache directories
cache_dirs=()
while IFS= read -r line; do
cache_dirs+=("$line")
done < <(find "$cache_dir" -type d -maxdepth 1 2>/dev/null | sort)
# Get sizes for each directory
cache_sizes=()
for dir in "${cache_dirs[@]}"; do
if [ -d "$dir" ]; then
size=$(du -sh "$dir" 2>/dev/null | cut -f1)
cache_sizes+=("$size")
else
cache_sizes+=("")
fi
done
# Display directories with their sizes
for i in "${!cache_dirs[@]}"; do
if [ -n "${cache_sizes[$i]}" ] && [ "${cache_dirs[$i]}" != "$cache_dir" ]; then
echo "$i) ${cache_sizes[$i]} - ${cache_dirs[$i]}"
fi
done
read -p "Enter numbers to clean (or 'all' for all, 'skip' to skip): " selections
if [ "$selections" = "all" ]; then
for i in "${!cache_dirs[@]}"; do
if [ "${cache_dirs[$i]}" != "$cache_dir" ] && [ -d "${cache_dirs[$i]}" ]; then
dir_name=$(basename "${cache_dirs[$i]}")
if confirm "Clean $dir_name (${cache_sizes[$i]})?" "n"; then
before_size=$(get_dir_size "${cache_dirs[$i]}")
rm -rf "${cache_dirs[$i]}"/*
print_success "$dir_name cache cleaned. Before: $before_size, After: $(get_dir_size "${cache_dirs[$i]}")"
fi
fi
done
elif [ "$selections" != "skip" ]; then
for sel in $selections; do
if [ -n "${cache_dirs[$sel]}" ] && [ "${cache_dirs[$sel]}" != "$cache_dir" ]; then
dir_name=$(basename "${cache_dirs[$sel]}")
before_size=$(get_dir_size "${cache_dirs[$sel]}")
rm -rf "${cache_dirs[$sel]}"/*
print_success "$dir_name cache cleaned. Before: $before_size, After: $(get_dir_size "${cache_dirs[$sel]}")"
fi
done
fi
fi
}
# Clean System Caches and Logs
clean_system_caches() {
print_header "Cleaning System Caches and Logs"
# macOS system logs
print_info "Checking system logs..."
if confirm "Clean system logs? This requires administrator privileges." "n"; then
print_warning "This will clear system logs. You'll be prompted for your password."
sudo rm -rf /private/var/log/*
print_success "System logs cleaned."
fi
# Temporary files
print_info "Checking temporary files..."
before_size=$(get_dir_size /tmp)
if confirm "Clean temporary files in /tmp?" "y"; then
rm -rf /tmp/* 2>/dev/null
print_success "Temporary files cleaned. Before: $before_size, After: $(get_dir_size /tmp)"
fi
# User cache
print_info "Checking user cache..."
before_size=$(get_dir_size "$HOME/Library/Caches")
if confirm "Clean all user caches? (This is aggressive and may remove important cached data)" "n"; then
find "$HOME/Library/Caches" -depth 1 -not -name "." -not -name ".." -exec rm -rf {} \; 2>/dev/null
print_success "User caches cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Caches")"
fi
# Clear DNS cache
if confirm "Clear DNS cache?" "y"; then
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
print_success "DNS cache flushed."
fi
# Application logs
if check_directory "$HOME/Library/Logs"; then
print_info "Checking application logs..."
before_size=$(get_dir_size "$HOME/Library/Logs")
if confirm "Clean application logs?" "y"; then
find "$HOME/Library/Logs" -type f -delete 2>/dev/null
print_success "Application logs cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Logs")"
fi
fi
# XCode derived data
if check_directory "$HOME/Library/Developer/Xcode/DerivedData"; then
print_info "Checking XCode derived data..."
before_size=$(get_dir_size "$HOME/Library/Developer/Xcode/DerivedData")
if confirm "Clean XCode derived data? This is safe but will require rebuilding projects." "y"; then
rm -rf "$HOME/Library/Developer/Xcode/DerivedData"/*
print_success "XCode derived data cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Developer/Xcode/DerivedData")"
fi
fi
# iOS Device Support files
if check_directory "$HOME/Library/Developer/Xcode/iOS DeviceSupport"; then
print_info "Checking iOS Device Support files..."
before_size=$(get_dir_size "$HOME/Library/Developer/Xcode/iOS DeviceSupport")
if confirm "Clean iOS Device Support files? These will be recreated when you connect iOS devices." "y"; then
rm -rf "$HOME/Library/Developer/Xcode/iOS DeviceSupport"/*
print_success "iOS Device Support files cleaned. Before: $before_size, After: $(get_dir_size "$HOME/Library/Developer/Xcode/iOS DeviceSupport")"
fi
fi
# macOS trash
print_info "Checking trash bin..."
if [ -d "$HOME/.Trash" ]; then
before_size=$(get_dir_size "$HOME/.Trash")
if [ "$before_size" != "0B" ]; then
if confirm "Empty trash bin? This action cannot be undone." "n"; then
rm -rf "$HOME/.Trash"/*
print_success "Trash emptied. Before: $before_size, After: $(get_dir_size "$HOME/.Trash")"
fi
else
print_info "Trash is already empty."
fi
fi
# Software update downloads
if check_directory "/Library/Updates"; then
if confirm "Clean software update downloads? This requires administrator privileges." "n"; then
print_warning "This will clear downloaded software updates. You'll be prompted for your password."
sudo rm -rf /Library/Updates/*
print_success "Software update downloads cleaned."
fi
fi
}
# Show disk usage summary
show_disk_usage() {
print_header "Disk Usage Summary"
# System disk usage
echo -e "${CYAN}System Disk Usage:${NC}"
df -h / | awk 'NR==1 || NR==2 {print}'
echo
# User directory sizes
echo -e "${CYAN}User Directory Sizes:${NC}"
du -h -d 1 ~ 2>/dev/null | sort -hr | head -n 10
echo
# Large directories
echo -e "${CYAN}Large Directories:${NC}"
du -h -d 2 ~ 2>/dev/null | sort -hr | head -n 5
echo
# Development caches
echo -e "${CYAN}Development Tool Caches:${NC}"
print_size "$HOME/Library/Caches/Homebrew"
print_size "$HOME/.npm"
print_size "$HOME/Library/Caches/pip"
print_size "$HOME/Library/Caches/Cypress"
print_size "$HOME/Library/Caches/pnpm"
print_size "$HOME/Library/Caches/ms-playwright"
echo
# Browser caches
echo -e "${CYAN}Browser Caches:${NC}"
print_size "$HOME/Library/Caches/Google/Chrome"
print_size "$HOME/Library/Caches/Firefox"
print_size "$HOME/Library/Caches/com.apple.Safari"
print_size "$HOME/Library/Caches/Microsoft Edge"
print_size "$HOME/Library/Caches/BraveSoftware/Brave-Browser"
echo
}
# Main menu
main_menu() {
local initial_free_space=$(get_free_space)
# Initial disk usage report
clear
print_header "MacOS Cleanup Utility"
echo -e "Current free space: ${GREEN}$initial_free_space${NC}"
echo
while true; do
echo -e "${CYAN}Please select an option:${NC}"
echo "1) Show disk usage summary"
echo "2) Clean development tool caches"
echo "3) Clean browser caches"
echo "4) Clean application caches"
echo "5) Clean system caches and logs"
echo "6) Run all cleanups"
echo "7) Exit"
echo
read -p "Enter your choice (1-7): " choice
echo
case $choice in
1)
show_disk_usage
;;
2)
clean_dev_caches
;;
3)
clean_browser_caches
;;
4)
clean_app_caches
;;
5)
clean_system_caches
;;
6)
print_header "Running All Cleanups"
print_warning "This will run all cleanup options. You'll be prompted for each action."
if confirm "Do you want to continue?" "n"; then
clean_dev_caches
clean_browser_caches
clean_app_caches
clean_system_caches
fi
;;
7)
break
;;
*)
print_error "Invalid choice. Please enter a number between 1 and 7."
;;
esac
echo
echo -e "Press Enter to return to the menu..."
read
clear
print_header "MacOS Cleanup Utility"
echo -e "Current free space: ${GREEN}$(get_free_space)${NC} (was ${BLUE}$initial_free_space${NC})"
echo
done
# Show final summary
local final_free_space=$(get_free_space)
print_header "Cleanup Complete"
echo -e "Initial free space: ${BLUE}$initial_free_space${NC}"
echo -e "Final free space: ${GREEN}$final_free_space${NC}"
# Calculate space saved
local initial_bytes=$(echo "$initial_free_space" | sed 's/G//g')
local final_bytes=$(echo "$final_free_space" | sed 's/G//g')
if (( $(echo "$final_bytes > $initial_bytes" | bc -l) )); then
local saved=$(echo "$final_bytes - $initial_bytes" | bc -l)
echo -e "You freed approximately ${GREEN}${saved}GB${NC} of disk space!"
fi
echo
print_info "Thank you for using the MacOS Cleanup Utility!"
echo
}
# Run main menu
main_menu