Level Verified

macOS Disk Cleanup Script

Frees up disk space by removing outdated temp files, cache folders, old downloads, system logs, and more. Keeps your Mac running smoothly with an automated cleaning process you can schedule or trigger on demand through Level.

Import into Level

Problem overview

Running out of disk space on macOS can lead to slow performance, application issues, and user frustration. Manually removing temporary files, caches, and outdated downloads is time-consuming. This script automates those cleanup tasks, helping you reclaim valuable storage and enhance overall system health.

Bash 300s timeout Runs as Local system macOS
#!/bin/bash

# This resource is provided as a convenience for Level users. We cannot 
# guarantee it will work in all environments. Please test before deploying 
# to your production environment. We welcome contributions to our community 
# library

# Level Library
# https://level.io/library/script-macos-disk-cleanup

# Create log file
LOG_FILE="/tmp/cleanup_$(date +%Y%m%d_%H%M).log"
TOTAL_SAVED=0

log_message() {
    echo "$1" | tee -a "$LOG_FILE"
}

get_size() {
    if [[ -e $1 ]]; then
        du -sk "$1" 2>/dev/null | cut -f1
    else
        echo "0"
    fi
}

delete_safely() {
    local path="$1"
    local desc="$2"
    
    if [[ -e "$path" ]]; then
        local size_before=$(get_size "$path")
        
        if rm -rf "$path" 2>/dev/null; then
            local freed=$((size_before))
            TOTAL_SAVED=$((TOTAL_SAVED + freed))
            log_message "Cleaned $desc - Freed $((freed/1024)) MB"
        else
            log_message "Skipped $desc - Could not delete (may be locked or permission denied)"
        fi
    fi
}

log_message "Cleanup started at $(date)"

# Clean various temp directories
TEMP_PATHS=(
    "/tmp/*"
    "/private/tmp/*"
    "/private/var/tmp/*"
    "$HOME/Library/Caches/*"
    "$HOME/Library/Logs/*"
    "$HOME/Library/Safari/Downloads/*"
)

log_message "Cleaning temporary files..."
for path in "${TEMP_PATHS[@]}"; do
    find "$path" -mindepth 1 -mtime +1 -print0 2>/dev/null | while IFS= read -r -d '' file; do
        if [[ ! -f "$file" ]] || lsof "$file" >/dev/null 2>&1; then
            continue
        fi
        delete_safely "$file" "temp file: $(basename "$file")"
    done
done

# Clean Downloads folder
log_message "Cleaning Downloads folder..."
if [[ -d "$HOME/Downloads" ]]; then
    find "$HOME/Downloads" -mindepth 1 -mtime +30 -print0 2>/dev/null | while IFS= read -r -d '' file; do
        if [[ ! -f "$file" ]] || lsof "$file" >/dev/null 2>&1; then
            continue
        fi
        delete_safely "$file" "old download: $(basename "$file")"
    done
fi

# Clean Chrome Cache (if Chrome is installed)
if [[ -d "$HOME/Library/Caches/Google/Chrome" ]]; then
    log_message "Cleaning Chrome Cache..."
    delete_safely "$HOME/Library/Caches/Google/Chrome/Default/Cache/*" "Chrome cache"
fi

# Clean system logs
log_message "Cleaning system logs..."
sudo rm -rf /private/var/log/*.log* 2>/dev/null
sudo rm -rf /private/var/log/asl/*.asl 2>/dev/null

# Clean XCode derived data (if XCode is installed)
if [[ -d "$HOME/Library/Developer/Xcode/DerivedData" ]]; then
    log_message "Cleaning XCode derived data..."
    delete_safely "$HOME/Library/Developer/Xcode/DerivedData" "XCode derived data"
fi

# Clean App Store cache
log_message "Cleaning App Store cache..."
delete_safely "$HOME/Library/Caches/com.apple.appstore" "App Store cache"

# Final summary
TOTAL_GB=$(echo "scale=2; $TOTAL_SAVED/1024/1024" | bc)
TOTAL_MB=$(echo "scale=2; $TOTAL_SAVED/1024" | bc)

log_message "Cleanup completed at $(date)"
log_message "-------------------------------------------"
log_message "Disk cleanup completed successfully."
log_message "Total space freed: ${TOTAL_MB} MB (${TOTAL_GB} GB)"
log_message "Log file saved to: $LOG_FILE"
log_message "-------------------------------------------"

# Empty trash
log_message "Emptying Trash..."

GUI_USER=$(stat -f '%Su' /dev/console)
USER_HOME=$(dscl . -read /Users/"$GUI_USER" NFSHomeDirectory | awk '{print $2}')
TRASH_PATH="$USER_HOME/.Trash"

if [[ -d "$TRASH_PATH" ]]; then
    find "$TRASH_PATH" -mindepth 1 -exec rm -rf {} + 2>/dev/null
    log_message "Trash emptied from $TRASH_PATH (user: $GUI_USER)."
else
    log_message "Trash folder not found at $TRASH_PATH or already empty (user: $GUI_USER)."
fi

This script searches key locations on macOS—like temporary directories, browser caches, and old download folders—then systematically removes files that are likely no longer needed. It also clears system logs and purges leftover developer data, all while logging its actions for easy review. By targeting files older than a specific age and skipping any that might still be in use, the script ensures a targeted, safe cleanup process that frees up space without risking critical system files.

You can integrate this script into Level for on-demand cleanups. Simply configure a script-based monitor to trigger the script automatically whenever disk space falls below a certain threshold, or use a scheduled automation to run it periodically.

Use cases

  • Quick recovery of disk space on macOS endpoints
  • Routine cleanup in MSP environments to maintain performance
  • Automating maintenance tasks for end-users or project-based systems
  • Integrating with Level monitors to proactively clear space when capacity is low

Recommendations

  • Test in a non-critical environment before wide deployment
  • Set up a script-based monitor in Level to automatically trigger when disk space dips below a threshold
  • Schedule periodic cleanups using a Level automation for ongoing maintenance
  • Review logs generated in /tmp to confirm proper cleanup
  • Customize target folders in the script if your organization stores files in unique locations

Frequently asked questions.

Will this script delete important user files?

The script targets specific directories known for temporary or old data. It avoids files in use by checking for open file handles, but always test first to confirm it suits your environment.

What happens if the script encounters locked files?

Locked or in-use files are skipped to prevent errors or data loss.

How often should I run this script?

It depends on your usage. Some MSPs schedule it weekly, while others tie it to a disk-space monitor in Level for on-demand triggers.

Can I modify which directories get cleaned?

Absolutely. You can add or remove directory paths in the script to align with your organization’s file management policies.

Is the log file saved permanently?

The log file is placed in /tmp with a date stamp. It will remain there until manually removed or cleared by your system’s temp file policies.

Ready when you are.

No credit card. No sales call. Just sign up and start managing.