#!/usr/bin/env bash # disk_cleanup_check.sh — Analyze disk usage and suggest (or perform) cleanup. # # Usage: # ./disk_cleanup_check.sh # Dry-run: report only # ./disk_cleanup_check.sh --clean # Interactive: prompt before each action # # Safe by default: nothing is deleted without --clean AND user confirmation. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # CLEAN and TOTAL_RECLAIMABLE must exist before the helpers are sourced: # `confirm` reads CLEAN and `report` accumulates into TOTAL_RECLAIMABLE. CLEAN=false if [[ "${1:-}" == "--clean" ]]; then CLEAN=true fi TOTAL_RECLAIMABLE=0 # shellcheck source=./lib/disk_cleanup_common.sh source "$SCRIPT_DIR/lib/disk_cleanup_common.sh" # ───────────────────── checks ───────────────────── printf "\n%s=== Disk Cleanup Analysis ===%s\n\n" "${BOLD}" "${RESET}" printf "${BOLD}%-40s %10s${RESET}\n" "Category" "Reclaimable" printf '%s\n' "$(printf '%.0s─' {1..60})" # 1. Trash trash_dir="$HOME/.local/share/Trash" size=$(dir_size_kb "$trash_dir") report "Trash" "$size" "empty trash" if ((size > 0)); then try_clean "Empty trash?" \ rm -rf "${trash_dir}/files" "${trash_dir}/info" "${trash_dir}/expunged" fi # 2. Pacman cache pacman_cache_size=$(dir_size_kb "/var/cache/pacman/pkg") if ((pacman_cache_size > 0)); then if command -v paccache &>/dev/null; then pkg_count=$(find /var/cache/pacman/pkg/ -maxdepth 1 -type f -name '*.pkg.tar*' 2>/dev/null | wc -l) report "Pacman cache ($pkg_count pkgs)" "$pacman_cache_size" \ "sudo paccache -rk2" try_clean "Clean pacman cache (keep last 2 versions)?" \ sudo paccache -rk2 else report "Pacman cache (install pacman-contrib)" "$pacman_cache_size" \ "pacman -S pacman-contrib && paccache -rk2" fi fi # 3. Yay build cache yay_cache="$HOME/.cache/yay" size=$(dir_size_kb "$yay_cache") report "Yay AUR build cache" "$size" "rm -rf ~/.cache/yay" if ((size > 0)); then try_clean "Clear yay build cache?" rm -rf "${yay_cache:?}" fi # 4. Pip cache pip_cache="$HOME/.cache/pip" size=$(dir_size_kb "$pip_cache") report "Pip cache" "$size" "pip cache purge" if ((size > 0)); then try_clean "Clear pip cache?" rm -rf "${pip_cache:?}" fi # 5. uv cache uv_cache="$HOME/.cache/uv" size=$(dir_size_kb "$uv_cache") report "uv cache" "$size" "uv cache clean" if ((size > 0)); then try_clean "Clear uv cache?" rm -rf "${uv_cache:?}" fi # 6. HuggingFace cache hf_cache="$HOME/.cache/huggingface" size=$(dir_size_kb "$hf_cache") report "HuggingFace models" "$size" "manual review recommended" # 7. Suno cache suno_cache="$HOME/.cache/suno" size=$(dir_size_kb "$suno_cache") report "Suno AI cache" "$size" "manual review recommended" # 8. Go build cache go_cache="$HOME/.cache/go-build" size=$(dir_size_kb "$go_cache") report "Go build cache" "$size" "go clean -cache" if ((size > 0)); then try_clean "Clear Go build cache?" rm -rf "${go_cache:?}" fi # 9. Yarn cache yarn_cache="$HOME/.cache/yarn" size=$(dir_size_kb "$yarn_cache") report "Yarn cache" "$size" "yarn cache clean" if ((size > 0)); then try_clean "Clear yarn cache?" rm -rf "${yarn_cache:?}" fi # 10. npm cache npm_cache="$HOME/.npm/_cacache" size=$(dir_size_kb "$npm_cache") report "npm cache" "$size" "npm cache clean --force" if ((size > 0)); then try_clean "Clear npm cache?" rm -rf "${npm_cache:?}" fi # 11. Electron cache electron_cache="$HOME/.cache/electron" size=$(dir_size_kb "$electron_cache") report "Electron cache" "$size" if ((size > 0)); then try_clean "Clear Electron cache?" rm -rf "${electron_cache:?}" fi # 12. Thumbnails thumb_cache="$HOME/.cache/thumbnails" size=$(dir_size_kb "$thumb_cache") report "Thumbnails cache" "$size" if ((size > 0)); then try_clean "Clear thumbnails?" rm -rf "${thumb_cache:?}" fi # 13. vscode-cpptools cache cpptools_cache="$HOME/.cache/vscode-cpptools" size=$(dir_size_kb "$cpptools_cache") if ((size > 102400)); then report "VS Code cpptools cache" "$size" try_clean "Clear cpptools cache?" rm -rf "${cpptools_cache:?}" fi # 14. Bazel cache bazel_cache="$HOME/.cache/bazel" size=$(dir_size_kb "$bazel_cache") report "Bazel cache" "$size" if ((size > 0)); then try_clean "Clear bazel cache?" rm -rf "${bazel_cache:?}" fi # 15. Browser caches (report only) for browser_cache in \ "$HOME/.cache/thorium" \ "$HOME/.cache/google-chrome" \ "$HOME/.cache/mozilla" \ "$HOME/.cache/BraveSoftware"; do if [[ -d "$browser_cache" ]]; then name=$(basename "$browser_cache") size=$(dir_size_kb "$browser_cache") if ((size > 102400)); then report "Browser cache: $name" "$size" "close browser first" fi fi done # 16. Docker if command -v docker &>/dev/null; then docker_dir="/var/lib/docker" size=$(dir_size_kb "$docker_dir" || echo 0) if ((size > 1048576)); then report "Docker (images+build cache)" "$size" "docker system prune -a" try_clean "Docker system prune (removes all unused)?" \ docker system prune -af --volumes fi fi # 17. Orphan packages orphans=$(pacman -Qdtq 2>/dev/null || true) orphan_count=0 if [[ -n "$orphans" ]]; then orphan_count=$(echo "$orphans" | wc -l) fi if ((orphan_count > 0)); then orphan_size=$(echo "$orphans" | xargs pacman -Qi 2>/dev/null | awk '/Installed Size/{ size=$4; unit=$5; if (unit ~ /GiB/) total += size*1048576; else if (unit ~ /MiB/) total += size*1024; else if (unit ~ /KiB/) total += size; } END{printf "%d", total}' || echo 0) report "Orphan packages ($orphan_count)" "$orphan_size" \ "sudo pacman -Rns \$(pacman -Qdtq)" if confirm "Remove $orphan_count orphan packages?"; then # shellcheck disable=SC2046 sudo pacman -Rns $(pacman -Qdtq) --noconfirm printf "%s ✓ Orphans removed%s\n" "${GREEN}" "${RESET}" fi fi # 18. Journal logs — vacuum to 200M journal_line=$(journalctl --disk-usage 2>&1 || true) journal_kb=0 if [[ "$journal_line" =~ ([0-9.]+)G ]]; then journal_kb=$(echo "${BASH_REMATCH[1]} * 1048576 / 1" | bc) elif [[ "$journal_line" =~ ([0-9.]+)M ]]; then journal_kb=$(echo "${BASH_REMATCH[1]} * 1024 / 1" | bc) fi if ((journal_kb > 204800)); then excess=$((journal_kb - 204800)) report "Journal logs (excess over 200M)" "$excess" "journalctl --vacuum-size=200M" try_clean "Vacuum journal to 200M?" \ sudo journalctl --vacuum-size=200M fi # 19. AUR source dirs — old archives (>30 days) aur_dir="$HOME/sdk/aur" if [[ -d "$aur_dir" ]]; then old_archives_kb=$(find "$aur_dir" \ \( -name "*.pkg.tar.zst" -o -name "*.tar.gz" -o -name "*.tar.xz" \ -o -name "*.zip" -o -name "*.tar.bz2" \) \ -mtime +30 -printf '%k\n' 2>/dev/null | awk '{t+=$1} END{print t+0}') if ((old_archives_kb > 0)); then report "AUR old archives (>30d)" "$old_archives_kb" \ "find ~/sdk/aur '*.pkg.tar.zst' -mtime +30 -delete" if confirm "Delete old AUR archives (>30 days)?"; then find "$aur_dir" \ \( -name "*.pkg.tar.zst" -o -name "*.tar.gz" -o -name "*.tar.xz" \ -o -name "*.zip" -o -name "*.tar.bz2" \) \ -mtime +30 -delete printf "%s ✓ Old AUR archives deleted%s\n" "${GREEN}" "${RESET}" fi fi fi print_report_only print_summary