#!/bin/bash # disk-breakdown: generate a visual breakdown of disk usage set -e # colors BOLD='\033[1m' DIM='\033[2m' RESET='\033[0m' GREEN='\033[32m' YELLOW='\033[33m' RED='\033[31m' # get disk info read -r SIZE USED AVAIL PERCENT <<< $(df -h /System/Volumes/Data | tail -1 | awk '{print $2, $3, $4, $5}') # color based on usage if [[ ${PERCENT%\%} -gt 90 ]]; then COLOR=$RED elif [[ ${PERCENT%\%} -gt 75 ]]; then COLOR=$YELLOW else COLOR=$GREEN fi echo "" echo -e "${BOLD}DISK: ${SIZE} total | ${COLOR}${USED} used${RESET} ${BOLD}| ${AVAIL} free (${PERCENT})${RESET}" echo "" # bar chart BAR_WIDTH=50 USED_PCT=${PERCENT%\%} USED_BARS=$((USED_PCT * BAR_WIDTH / 100)) FREE_BARS=$((BAR_WIDTH - USED_BARS)) echo -n "[" printf "${COLOR}%0.s█${RESET}" $(seq 1 $USED_BARS) 2>/dev/null || true printf "${DIM}%0.s░${RESET}" $(seq 1 $FREE_BARS) 2>/dev/null || true echo "]" echo "" # home breakdown echo -e "${BOLD}~ breakdown:${RESET}" dust -d 1 ~ 2>/dev/null | grep -E "^\s*[0-9]+(\.[0-9]+)?[KMGT]?\s" | tail -20 echo "" echo -e "${BOLD}other:${RESET}" echo " /Applications: $(dust -d 0 /Applications 2>/dev/null | awk '{print $1}')" echo " /opt: $(dust -d 0 /opt 2>/dev/null | awk '{print $1}')" # snapshots SNAPS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -c "com.apple" || true) if [[ -n "$SNAPS" && "$SNAPS" -gt 0 ]]; then echo "" echo -e "${YELLOW}⚠ $SNAPS APFS snapshot(s) may be holding space${RESET}" fi # pending updates (skip if slow) if [[ "${1:-}" != "-q" ]]; then UPDATES=$(timeout 5 softwareupdate -l 2>&1 | grep -c "Label:" || true) if [[ -n "$UPDATES" && "$UPDATES" -gt 0 ]]; then echo -e "${YELLOW}⚠ $UPDATES pending update(s) - install to clear snapshots${RESET}" fi fi # docker check DOCKER_RAW="$HOME/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw" if [[ -f "$DOCKER_RAW" ]]; then ACTUAL=$(du -sh "$DOCKER_RAW" 2>/dev/null | awk '{print $1}') ALLOC=$(ls -lh "$DOCKER_RAW" 2>/dev/null | awk '{print $5}') echo "" echo -e "${DIM}docker: ${ACTUAL} actual / ${ALLOC} allocated${RESET}" fi # summary echo "" echo -e "${BOLD}totals:${RESET}" APFS_USED=$(diskutil apfs list 2>/dev/null | grep "Capacity In Use" | head -1 | grep -oE '[0-9.]+ GB' | head -1) APFS_FREE=$(diskutil apfs list 2>/dev/null | grep "Not Allocated" | head -1 | grep -oE '[0-9.]+ GB' | head -1) DATA_VOL=$(diskutil apfs list 2>/dev/null | grep -A3 "Role.*Data" | grep "Capacity Consumed" | grep -oE '[0-9.]+ GB') echo " APFS used: $APFS_USED" echo " APFS free: $APFS_FREE" echo " Data volume: $DATA_VOL" echo "" echo -e "${DIM}$(date '+%Y-%m-%d %H:%M')${RESET}"