From c3b0fc619b7a03a08a7f4703f6fba456def321c2 Mon Sep 17 00:00:00 2001 From: Skydust Date: Sat, 14 Oct 2023 18:46:49 +0200 Subject: [PATCH] Rewrote a lot of stuff to support a config file in fucking bash. Why do I do this to myself --- Clear.sh | 453 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 305 insertions(+), 148 deletions(-) diff --git a/Clear.sh b/Clear.sh index de61d4c..93509b9 100755 --- a/Clear.sh +++ b/Clear.sh @@ -1,8 +1,7 @@ -#!/bin/sh +#!/bin/zsh +Version="2.0" -Version="1.2" - -# Colors +# ------ COLOR SETUP ------ # # Reset Color_Off='\033[0m' # Text Reset @@ -35,12 +34,24 @@ SizeColor=$Green ClearableNameColor=$Yellow NotFoundColor=$Purple ResultSizeColor=$Green +CategoryColor=$BYellow FoundText="${FoundColor}Found !${Color_Off}" +# ------ CORE ------ # + +config_folder_filepath="${HOMEBREW_PREFIX}/etc/clearscript" +config_filepath="${config_folder_filepath}/config.cfg" + +# Stops the script on any failure set -e -# Sudo function +# Array definitions +typeset -A jobSteps +typeset -A jobCategories # Associative arrays cannot contain other arrays, so this will contain strings with newlines as a workaround +typeset -A jobEnabled + +# Upgrade the script permissions using sudo asksudo() { echo "Checking for sudo permissions..." if [[ "$EUID" = 0 ]]; then @@ -56,131 +67,66 @@ asksudo() { fi } -# -- Clearing functions -- # -coreSimClear() { - CoreSimCaches="${HOME}/Library/Developer/CoreSimulator/Caches" - - echo "${BarColor}====== ${ClearableNameColor}CoreSimulator ${BarColor}======${Color_Off}" - echo "Checking for ${ClearableNameColor}CoreSimulator${Color_Off}'s cache folder..." - - #if [[ -d "$CoreSimCaches" ]] - if [ -n "$(ls -d ${CoreSimCaches}/* 2>/dev/null)" ]; - then - echo "${FoundText}" - - echo "Deleting ${ClearableNameColor}CoreSimulator${Color_Off}'s cache... ${SizeColor}($(du -sh ${CoreSimCaches} | cut -f1))${Color_Off}" - cleared=$(($cleared+$(du -sk ${CoreSimCaches} | cut -f1))) - sudo rm -rv ${CoreSimCaches}/* | pv -l -s $(du -a ${CoreSimCaches} | wc -l)> /dev/null +# Add a job to cleanup something +# Arguments: +# - Category | The category of the job +# - Name | The name of the job +# - Step | Can be either a function or a folder path +addJob() { + local category="$1" + local name="$2" + local step="$3" + + jobSteps["$name"]="$step" + + if [[ -z $jobCategories["$category"] ]]; then + jobCategories["$category"]="$name" else - echo "${ClearableNameColor}CoreSimulator${Color_Off}'s cache ${NotFoundColor}not found${Color_Off}." + jobCategories["$category"]+="\n$name" fi } -gradleJavaClear() { - GradleJarFiles="${HOME}/.gradle/caches" - - echo "${BarColor}====== ${ClearableNameColor}Gradle ${BarColor}======${Color_Off}" - echo "Checking for ${ClearableNameColor}gradle${Color_Off} java cache folders..." +# Shows a title for a job element +# Arguments: +# - jobName | The job name +jobTitle() { + local jobName="$1" - if [ -n "$(ls -d ${GradleJarFiles}/jars-* 2>/dev/null)" ]; - then - echo "${FoundText}" - - echo "Clearing ${ClearableNameColor}Gradle${Color_Off} java caches... ${SizeColor}($(du -sch ${GradleJarFiles}/jars-* | grep 'total' | cut -f1))${Color_Off}" - cleared=$(($cleared+$(du -sck ${GradleJarFiles}/jars-* | grep 'total' | cut -f1))) - sudo rm -rv ${GradleJarFiles}/jars-* | pv -l -s $(du -a ${GradleJarFiles}/jars-* | wc -l)> /dev/null - else - echo "${ClearableNameColor}Gradle${Color_Off} java cache folders ${NotFoundColor}not found${Color_Off}." - fi + echo + echo "${BarColor}[ ${ClearableNameColor}${jobName} ${BarColor}]${Color_Off}" } -################################################### +# Takes a size value and returns a human readable version. +# Arguments: +# - Return variable | The formatted variable +# - valueInBytes | The size in bytes +getHumanReadableValue() { + local valueInBytes="$2" -## Clean out older Fusion 360 installations - -################################################### - -function deleteOldestInstallFusion360 () { - echo "${BarColor}====== ${ClearableNameColor}Clearing outdated Fusion360 versions ${BarColor}======${Color_Off}" - - local targetDirectory="${HOME}/Library/Application Support/Autodesk/webdeploy/production" - - if [[ -d "$targetDirectory" ]] - then - local linkToFind="$(readlink ${HOME}/Library/Application\ Support/Autodesk/webdeploy/production/Autodesk\ Fusion\ 360.app)" - local extractedFolderName="$(basename "$(dirname "$linkToFind")")" - - echo "Target Directory is '""$targetDirectory""'" - echo "Currently used Fusion360 folder: ${extractedFolderName}" - - if [ "$extractedFolderName" == "" ] || [ "$extractedFolderName" == "." ]; - then - echo "${NotFoundColor}Unable to find the right folder${Color_Off}" - else - if [ "$linkToFind" == "" ]; - then - echo "${NotFoundColor}Unable to find the right folder${Color_Off}" - else - local toDelete=0 - # Calculating the size of files to delete with an overly complex command - toDelete=$(($toDelete$(find "$targetDirectory" -mindepth 1 -maxdepth 1 ! -name "$extractedFolderName" ! -name "Autodesk Fusion 360.app" ! -name ".DS_Store" -exec bash -c 'echo -n "+$(du -sk "$0" | cut -f1)"' "{}" \; ))) - - echo "Deleting folders... ${SizeColor}($(($toDelete/1024))M)${Color_Off}" - - # Updating cleared - cleared=$(($cleared+$toDelete)) - - # Clearing folders w/ progression - find "$targetDirectory" -mindepth 1 -maxdepth 1 ! -name "$extractedFolderName" ! -name "Autodesk Fusion 360.app" ! -name ".DS_Store" -exec sh -c 'sudo rm -rv "$0" | pv -l -s $(du -a "$0" | wc -l)> /dev/null' "{}" \; - - echo "Done!" - fi - fi - else - echo "${ClearableNameColor}Fusion360${Color_Off}'s folder ${NotFoundColor}not found${Color_Off}." - fi -} - -clearDocker() { - if docker_exists="$(type -p "docker")" || [[ -z $docker_exists ]]; - then - echo "${BarColor}====== ${ClearableNameColor}Docker ${BarColor}======${Color_Off}" - if [ "$(docker ps -a -q | wc -l)" -gt "0" ]; - then - echo "Found running docker containers, stopping them..." - docker stop $(docker ps -a -q) - docker rm $(docker ps -a -q) - fi - docker system prune --all --force - else - echo "${ClearableNameColor}Docker${Color_Off} was ${NotFoundColor}not found${Color_Off}." - fi -} - - -clearFolderNew() { - local folderPath="$2" - local clearableName="$1" - - echo $folderPath - - echo "${BarColor}====== ${ClearableNameColor}${clearableName} ${BarColor}======${Color_Off}" - echo "Checking for ${ClearableNameColor}${clearableName}${Color_Off}'s cache folder..." - - if [ -n "$(find "${folderPath}" -mindepth 1 -maxdepth 1 2>/dev/null)" ]; - then - echo "${FoundText}" - - echo "Clearing ${ClearableNameColor}${clearableName}${Color_Off}'s cache... ${SizeColor}($(du -sh "${folderPath}" | cut -f1))${Color_Off}" - - addClearedVal cleared "$(du -sk "${folderPath}" | cut -f1)" - - sudo rm -rv "${folderPath}"/* | pv -l -s $(du -a "${folderPath}" | wc -l)> /dev/null - else - echo "${ClearableNameColor}${clearableName}${Color_Off}'s cache ${NotFoundColor}not found${Color_Off}." + if [[ -z $valueInBytes ]]; then + valueInBytes=0; fi + + local human_readable=0 + + if [[ $valueInBytes -ge 1073741824 ]]; then + human_readable="$(($valueInBytes / 1073741824)) GB" + elif [[ $valueInBytes -ge 1048576 ]]; then + human_readable="$(($valueInBytes / 1048576)) MB" + elif [[ $valueInBytes -ge 1024 ]]; then + human_readable="$(($valueInBytes / 1024)) KB" + else + human_readable="${valueInBytes} bytes" + fi + + local return_var="$1" + eval "$return_var"='$human_readable' } +# Updates the cleared value in bytes +# Arguments: +# - Return variable | Updated cleared value +# - clearedValueToAdd | A number to add to the current cleared value. addClearedVal() { local clearedValueToAdd="$2" @@ -197,28 +143,237 @@ addClearedVal() { eval "$return_var"='$cleared' } -# ------------------------ # +# Function used to clear every simple folder. +# Arguments: +# - clearableName | The name of the job. +# - folderPath | The path of the folder to remove the content of. +clearFolderNew() { + local folderPath="$2" + local clearableName="$1" + + jobTitle "$clearableName" + echo "Checking for ${ClearableNameColor}${clearableName}${Color_Off}'s cache folder..." -# -- Steps -- # + if [ -n "$(find "${folderPath}" -mindepth 1 -maxdepth 1 2>/dev/null)" ]; + then + echo "${FoundText}" -browserCleanup() { - clearFolderNew "Firefox" "${HOME}/Library/Caches/Firefox" + sizeToClear="$(du -sk "${folderPath}" | cut -f1)" + + getHumanReadableValue readableSize $sizeToClear + + echo "Clearing ${ClearableNameColor}${clearableName}${Color_Off}'s cache... ${SizeColor}(${readableSize})${Color_Off}" + + addClearedVal cleared $sizeToClear + + sudo rm -rv "${folderPath}"/* | pv -l -s $(du -a "${folderPath}" | wc -l)> /dev/null + else + echo "${ClearableNameColor}${clearableName}${Color_Off}'s cache ${NotFoundColor}not found${Color_Off}." + fi } -developmentCleanup() { - # Don't delete the folder - clearFolderNew "CoreSimulator" "${HOME}/Library/Developer/CoreSimulator/Caches" +# Runs every job +runJobs() { + # Elevate permissions... + asksudo - gradleJavaClear + for category in ${(k)jobCategories}; do + echo + echo "${BarColor}[ --====-- $CategoryColor$category${BarColor} --====-- ]${Color_Off}" - clearFolderNew "JetBrains" "${HOME}/Library/Caches/JetBrains" + echo "$jobCategories[$category]" | while IFS= read -r jobName; do + if [[ "${jobEnabled["\"$jobName\""]}" = true ]]; then + local step=$jobSteps["$jobName"] - clearFolderNew "VisualStudioInstaller" "${HOME}/Library/Caches/VisualStudioInstaller" - - clearFolderNew "VisualStudio" "${HOME}/Library/Caches/VisualStudio" + if print -l ${(ok)functions} | grep -q "^$step$"; then + jobTitle "$jobName" + # Running the custom job function + $step + else + clearFolderNew "$jobName" "$step" + fi + fi + done + done } -# ------------------------ # + +read_config_file() { + if [[ ! -f "$config_filepath" ]]; then + if [[ ! -d "$config_folder_filepath" ]]; then + mkdir -p $config_folder_filepath + fi + touch $config_filepath + fi + + while IFS= read -r line; do + parts=(${(s/=/)line}) + + configKey=${parts[1]} + configValue=${parts[2]} + + # Hard code values to prevent a broken config file from destroying everything + if [ "$configValue" = true ]; then + jobEnabled["$configKey"]=true; + else + jobEnabled["$configKey"]=false; + fi + done < $config_filepath + + for job in ${(k)jobSteps}; do + # If the job doesn't exist in the config file then it should be added in it + if [[ -z "${jobEnabled["$job"]}" ]]; then + echo "${job}=false" >> $config_filepath + jobEnabled["$job"]=false; + fi + done +} + +configure() { + local doneEverything=false + while [[ $doneEverything = false ]]; do + typeset -A optionsToJob + + local all_options=() + for job in ${(k)jobSteps}; do + local current_option="" + if [[ "${jobEnabled["$job"]}" = true ]]; then + current_option="[ON] ${job}" + else + current_option="[OFF] ${job}" + fi + optionsToJob["$current_option"]="$job" + all_options+=("$current_option") + done + all_options+=("Done") + + clear + + echo "=== CONFIGURATOR ===" + echo "Choose what you want to be enabled: " + select option in "${all_options[@]}"; do + array_length=${#all_options[@]} + if (( $REPLY < 0 || $REPLY > $array_length )); then + echo "Invalid choice. Please select a valid option." + break + elif [[ $REPLY = $array_length ]]; then + doneEverything=true + break + else + jobToEdit=${optionsToJob["${all_options[$REPLY]}"]} + local newValue="" + if [[ "${jobEnabled["$jobToEdit"]}" = true ]]; then + newValue=false + else + newValue=true + fi + + # Modifying the value inside the config file + sed -i -e "/^${jobToEdit}=/ s/=.*/=${newValue}/" "$config_filepath" + break + fi + done + read_config_file # Reread updated config file + done +} + +# ------ CUSTOM CLEANUP FUNCTIONS ------ # + +gradleJavaClear() { + GradleJarFiles="${HOME}/.gradle/caches" + + echo "Checking for ${ClearableNameColor}gradle${Color_Off} java cache folders..." + + if [ -n "$(ls -d ${GradleJarFiles}/jars-* 2>/dev/null)" ]; + then + echo "${FoundText}" + + sizeToClear="$(du -sck ${GradleJarFiles}/jars-* | grep 'total' | cut -f1)" + + getHumanReadableValue readableSize $sizeToClear + + echo "Clearing ${ClearableNameColor}Gradle${Color_Off} java caches... ${SizeColor}($readableSize)${Color_Off}" + addClearedVal cleared $sizeToClear + + sudo rm -rv ${GradleJarFiles}/jars-* | pv -l -s $(du -a ${GradleJarFiles}/jars-* | wc -l)> /dev/null + else + echo "${ClearableNameColor}Gradle${Color_Off} java cache folders ${NotFoundColor}not found${Color_Off}." + fi +} + +# Clean out older Fusion 360 installations +deleteOldestInstallFusion360() { + echo "Clearing outdated Fusion360 versions" + + local targetDirectory="${HOME}/Library/Application Support/Autodesk/webdeploy/production" + + if [[ -d "$targetDirectory" ]] + then + local linkToFind="$(readlink ${HOME}/Library/Application\ Support/Autodesk/webdeploy/production/Autodesk\ Fusion\ 360.app)" + local extractedFolderName="$(basename "$(dirname "$linkToFind")")" + + echo "Target Directory is '""$targetDirectory""'" + echo "Currently used Fusion360 folder: ${extractedFolderName}" + + if [ "$extractedFolderName" = "" ] || [ "$extractedFolderName" = "." ]; + then + echo "${NotFoundColor}Unable to find the right folder${Color_Off}" + else + if [ "$linkToFind" = "" ]; + then + echo "${NotFoundColor}Unable to find the right folder${Color_Off}" + else + local toDelete=0 + # Calculating the size of files to delete with an overly complex command + toDelete=$(($toDelete$(find "$targetDirectory" -mindepth 1 -maxdepth 1 ! -name "$extractedFolderName" ! -name "Autodesk Fusion 360.app" ! -name ".DS_Store" -exec bash -c 'echo -n "+$(du -sk "$0" | cut -f1)"' "{}" \; ))) + + getHumanReadableValue readableSize $toDelete + + echo "Deleting folders... ${SizeColor}(${readableSize})${Color_Off}" + + # Updating cleared + addClearedVal cleared $toDelete + + # Clearing folders w/ progression + find "$targetDirectory" -mindepth 1 -maxdepth 1 ! -name "$extractedFolderName" ! -name "Autodesk Fusion 360.app" ! -name ".DS_Store" -exec sh -c 'sudo rm -rv "$0" | pv -l -s $(du -a "$0" | wc -l)> /dev/null' "{}" \; + + echo "Done!" + fi + fi + else + echo "${ClearableNameColor}Fusion360${Color_Off}'s folder ${NotFoundColor}not found${Color_Off}." + fi +} + +clearDocker() { + if docker_exists="$(type -p "docker")" || [[ -z $docker_exists ]]; + then + if [ "$(docker ps -a -q | wc -l)" -gt "0" ]; + then + echo "Found running docker containers, stopping them..." + docker stop $(docker ps -a -q) + docker rm $(docker ps -a -q) + fi + docker system prune --all --force + else + echo "${ClearableNameColor}Docker${Color_Off} was ${NotFoundColor}not found${Color_Off}." + fi +} + +# -- Steps definitions -- # + +addJob "Development" "JetBrains" "${HOME}/Library/Caches/JetBrains" +addJob "Development" "CoreSimulator" "${HOME}/Library/Developer/CoreSimulator/Caches" +addJob "Development" "VisualStudioInstaller" "${HOME}/Library/Caches/VisualStudioInstaller" +addJob "Development" "Gradle java" gradleJavaClear +addJob "Development" "VisualStudio" "${HOME}/Library/Caches/VisualStudio" +addJob "Development" "Docker" clearDocker +addJob "Browser" "Firefox" "${HOME}/Library/Caches/Firefox" +addJob "Mail" "Thunderbird" "${HOME}/Library/Caches/Thunderbird" +addJob "Miscellaneous" "Homebrew" "${HOME}/Library/Caches/Homebrew" +addJob "Miscellaneous" "Discord" "${HOME}/Library/Application Support/discord/Cache" +addJob "Miscellaneous" "Adobe" "${HOME}/Library/Caches/Adobe" +addJob "Miscellaneous" "Fusion360 Old Installations" deleteOldestInstallFusion360 # -- Main Script -- # @@ -227,28 +382,30 @@ echo " Script ${ProgNameColor}Clear.sh${Color_Off} by ${AuthorNameColor}S echo " ${VersionColor}v${Version}${Color_Off} " echo "${BarColor}==========================================${Color_Off}" -# Elevate permissions... -asksudo +read_config_file -# Clearing... -developmentCleanup +while true; do + local response -browserCleanup + print -n "Want to configure? (y/N): " + read response -clearFolderNew "Thunderbird" "${HOME}/Library/Caches/Thunderbird" + # Check the response + case "$response" in + [yY]) + configure + ;; + *) + break + ;; + esac +done -clearFolderNew "Homebrew" "${HOME}/Library/Caches/Homebrew" +runJobs -# Discord needs to not have its cache folder deleted fully -clearFolderNew "Discord" "${HOME}/Library/Application Support/discord/Cache" - -clearFolderNew "Adobe" "${HOME}/Library/Caches/Adobe" - -deleteOldestInstallFusion360 - -clearDocker +getHumanReadableValue readableSize $cleared # Print final echo "${BarColor}==========================================${Color_Off}" -echo "Cleared ${ResultSizeColor}$(($cleared/1024))M${Color_Off} !" +echo "Cleared ${ResultSizeColor}${readableSize}${Color_Off} !" echo "${BarColor}==========================================${Color_Off}"