#!/bin/bash # Color Utilities function green() { printf "\033[32m%s\033[0m\n\n" "$1"; } function orange() { printf "\033[38;5;208m%s\033[0m\n" "$1"; } function red() { printf "\033[91m%s\033[0m\n" "$1"; } function blue() { printf "\033[38;5;27m%s\033[0m\n" "$1"; } # Constants BACKUP_DIR="$HOME/backups" FILENAME="$BACKUP_DIR/$(date +%d_%m_%Y).tar" # Create backup directory if it doesn't exist function ensure_backup_dir() { if [[ ! -e "$BACKUP_DIR" ]]; then blue "Creating backup directory." mkdir -p "$BACKUP_DIR" fi } # Handle existing backup file function check_existing_backup() { if [[ -f "$FILENAME" ]]; then orange "$FILENAME already exists!" read -rp "Do you want to remove the existing backup file? (y/n) : " answer [[ $answer == 'y' ]] && rm "$FILENAME" || exit 1 fi } # Brew function generate_config_files() { green "Preparing brew ..." local brew_file="$HOME/Brewfile" brew bundle dump --force --no-go --no-cargo --no-uv --no-npm --file="$brew_file" tar -rpf "$FILENAME" "$brew_file" } # Backup dotfiles function backup_dotfiles() { green "Backing up dotfiles..." find "$HOME"/.* -maxdepth 0 -type f \ -not -name ".claude.json" \ -not -name ".CFUserTextEncoding" \ -not -name ".DS_Store" \ -exec tar -rpf "$FILENAME" {} + } # Exclude large config dirs and create gzipped archive of .config function backup_config_gz() { tar -rpf "$FILENAME" "$HOME/.config/git" tar -rpf "$FILENAME" "$HOME/.config/rclone" tar -rpf "$FILENAME" "$HOME/.config/telebit" tar -rpf "$FILENAME" "$HOME/.config/yarn/global/package.json" tar -rpf "$FILENAME" "$HOME/.gnupg/*.gpg" tar -rpf "$FILENAME" "$HOME/.gradle/gradle.properties" tar -rpf "$FILENAME" "$HOME/.android/debug.keystore" } # Append selected items to tar archive function backup_specific_items() { green "Backing up specific items..." tar -rpf "$FILENAME" --exclude=".git" "$HOME/.zsh" tar -rpf "$FILENAME" --exclude="agent" --exclude="known_hosts" "$HOME/.ssh" tar -rpf "$FILENAME" $HOME/Library/LaunchAgents/local.* tar -rpf "$FILENAME" $HOME/Data/launchd/*/*.sh # tar -rpf "$FILENAME" "$HOME/Library/Developer/Xcode/UserData/KeyBindings" tar -rpf "$FILENAME" /etc/hosts /etc/paths } # Append list of backed-up files function add_backup_log() { { echo -e "\n\nBackup List:\n" tar -tvf "$FILENAME" | sort -k5 -rn } >backup_log.txt tar -rpf "$FILENAME" backup_log.txt blue backup log cat backup_log.txt rm backup_log.txt } # Validate final backup size function validate_backup_size() { local size size_mb size=$(stat -f "%z" "$FILENAME") size_mb=$(echo "scale=2; $size / 1024 / 1024" | bc) blue "$FILENAME has size ${size_mb} MB" if [[ $size -gt 24000000 ]]; then red "Backup > 24 MB, aborting." exit 1 else green "Done!" fi } # === Main Execution === ensure_backup_dir check_existing_backup cd "$HOME" || exit 1 generate_config_files backup_dotfiles backup_config_gz backup_specific_items add_backup_log validate_backup_size exit 0 # Restore with: # sudo tar -xvf .tar -C / # brew bundle install --file=~/Brewfile