Project Backup & Sync Script

This guide provides information about the project backup and synchronization script to backup your entire projects folder to another location, how to use it, and its full content for reference.

Script Overview & Usage

Understand what the script does and how to run it.

Purpose

The script synchronizes all files and directories from a specified source directory to a target directory. It creates a mirror of the source, overwriting newer files and deleting files from the target if they are no longer in the source. This is a great way to backup your entire projects folder to another location as an additional backup.

How it Works

It uses the rsync command with options for archiving (preserving file attributes), verbose output, itemizing changes, and deleting extraneous files from the target. A temporary log file is used to report on deleted files and is removed after the script completes. No permanent logs are kept by the script itself.

How to Use

1. Download the script:

Download project_backup.sh

2. Important: Open the downloaded project_backup.sh file in your code editor (Cursor, VS Code, etc.) or a text editor and update the following lines to match your desired source and target directories:

TARGET_DIR="/YOUR_TARGET_DESTINATION_HERE/"
SOURCE_DIR="/YOUR_SOURCE_DIRECTORY_HERE/"

3. Make it executable (run this in your terminal in the directory where you saved the script):

chmod +x project_backup.sh

4. Run the script (from the same directory):

./project_backup.sh

Log File Information

A temporary log file is created by mktemp during the script's execution to store the output of the rsync command. This file is used to report on deleted items and is automatically deleted after the synchronization report is generated. It is not persisted. If rsync fails, the contents of this temporary log are printed to the console for debugging before it's deleted.

Automating the Script (Optional)

Set up the script to run on a schedule.

macOS (using cron)

You can use cron, a time-based job scheduler in Unix-like operating systems, to run the script automatically. First, ensure the script is executable (chmod +x /path/to/your/project_backup.sh) and that the paths within the script are absolute or correctly resolvable by the cron environment.

Edit your crontab:

crontab -e

Then, add a line to schedule your script. For example, to run it daily at 2:00 AM:

0 2 * * * /path/to/your/project_backup.sh

(Replace /path/to/your/project_backup.sh with the actual absolute path to where you saved the script). You might want to redirect the script's output to a log file as well (e.g., >> /path/to/your/backup.log 2>&1 added after the script path).

Windows (using Task Scheduler)

Windows users can use Task Scheduler to automate the script. Since this is a Bash script, you'll typically run it via the Windows Subsystem for Linux (WSL) or Git Bash.

  1. Open Task Scheduler (search for it in the Start Menu).
  2. Click "Create Basic Task..." or "Create Task...".
  3. Give your task a name (e.g., "Project Backup Sync") and description.
  4. Set up a trigger (e.g., Daily, Weekly, at a specific time).
  5. For the "Action", select "Start a program".
  6. In "Program/script":
    • If using WSL: wsl or the path to your wsl.exe. Arguments would be the path to the script within WSL (e.g., /mnt/c/path/to/your/project_backup.sh).
    • If using Git Bash: The path to your bash.exe (usually in the Git installation directory, e.g., C:\Program Files\Git\bin\bash.exe). Arguments would be the path to your script (e.g., C:/path/to/your/project_backup.sh).
  7. In "Add arguments (optional)": If not included with the program/script path, provide the full path to your project_backup.sh script. Ensure paths are correctly formatted for the chosen shell.
  8. In "Start in (optional)": You might need to set this to the directory containing your script, or ensure all paths within the script are absolute.
  9. Review and finish the task setup. You may need to adjust permissions or ensure the script can run non-interactively.

Testing the task manually is recommended to ensure it runs as expected.

Alternative Backup Approaches

Other ways to keep your projects safe.

Git-Based Backups

Using Git and GitHub (or GitLab, Bitbucket) is one of the best ways to back up your code. Every commit is a snapshot you can return to, and pushing to a remote repository gives you an off-site copy automatically. Make frequent commits with descriptive messages and push regularly.

git add . && git commit -m 'backup: pre-refactor snapshot' && git push origin main

Cloud Backup Tips

For an extra layer of protection, consider syncing your projects folder to a cloud service like iCloud, Google Drive, OneDrive, or Dropbox. Many of these services offer free tiers with enough storage for code projects. You can also use an external SSD or NAS for local redundancy. The key principle is the 3-2-1 rule: 3 copies of your data, on 2 different media, with 1 off-site.

Script Content

The full content of project_backup.sh for reference.

#!/bin/bash

# === project_backup.sh ===
#
# Purpose:
#   Synchronizes all files and directories from a SOURCE_DIR to a TARGET_DIR.
#   This script is designed to create a mirror of the source on the target.
#   It will overwrite files in the target if the source has newer versions,
#   and it will delete files from the target if they are no longer in the source.
#
# How it works:
#   1. Defines Source and Target directories.
#   2. Creates the Target directory if it doesn't already exist.
#   3. Uses \`rsync\` with the following key options:
#      - \`-a\` (archive): Preserves permissions, ownership, timestamps, etc.
#      - \`-v\` (verbose): Provides more output about what is happening.
#      - \`--itemize-changes\`: Outputs a detailed list of changes.
#      - \`--delete\`: Deletes files from the TARGET_DIR that are not in the SOURCE_DIR.
#   4. Captures the \`rsync\` output into a TEMPORARY log file (created by \`mktemp\`).
#      This log file is used to generate a report of deleted files and is then
#      REMOVED at the end of the script. It is NOT stored permanently.
#   5. Reports on:
#      - Files deleted from the target directory during the sync.
#      - Total raw counts of directories and files in both source and target.
#
# Exclusions:
#   Currently, NO files or directories are excluded. Everything in the SOURCE_DIR
#   will be synchronized to the TARGET_DIR.
#
# Log File:
#   A temporary log file is created by \`mktemp\` during the script's execution
#   to store the output of the \`rsync\` command. This file is automatically
#   deleted after the synchronization report is generated. It is not persisted.
#   If \`rsync\` fails, the contents of this temporary log are printed to the console
#   to aid in debugging before it's deleted.
#
#   To enable, run chmod +x project_backup.sh

# Set source and target directories
TARGET_DIR="/YOUR_TARGET_DESTINATION_HERE/"
SOURCE_DIR="/YOUR_SOURCE_DIRECTORY_HERE/"

# Colors for output
GREEN='\\033[0;32m'
RED='\\033[0;31m'
YELLOW='\\033[0;33m'
NC='\\033[0m' # No Color

echo -e "\${GREEN}Starting synchronization of projects at \$(date)\${NC}"
echo -e "\${YELLOW}Source: \${SOURCE_DIR}\${NC}"
echo -e "\${YELLOW}Target: \${TARGET_DIR}\${NC}"

# Create target directory if it doesn't exist
mkdir -p "\$TARGET_DIR"

# Temporary file for rsync itemized output
RSYNC_LOG_FILE=\$(mktemp)

# Synchronize files, itemize changes
echo -e "\n\${YELLOW}Synchronizing files...\${NC}"
if rsync -av --itemize-changes --delete \\
    "\$SOURCE_DIR/" \\
    "\$TARGET_DIR/" > "\$RSYNC_LOG_FILE"; then
    SYNC_SUCCESS=true
    echo -e "\${GREEN}Project synchronization successful\${NC}"
else
    SYNC_SUCCESS=false
    echo -e "\${RED}Project synchronization failed. Check rsync output below:\${NC}"
    cat "\$RSYNC_LOG_FILE"
fi

echo -e "\n\${YELLOW}--- Synchronization Report ---\${NC}"
DELETED_COUNT=0
if [ "\$SYNC_SUCCESS" = true ]; then
    echo -e "\${YELLOW}Files deleted from target (\${TARGET_DIR}):\${NC}"
    grep "^\\*deleting" "\$RSYNC_LOG_FILE" | while IFS= read -r line; do
        filename="\${line:11}" 
        echo -e "\${RED}- \${filename}\${NC}"
        DELETED_COUNT=\$((\$DELETED_COUNT + 1))
    done
    if [ "\$DELETED_COUNT" -eq 0 ]; then
        echo "No files were deleted from target."
    fi
else
    echo "Synchronization failed, so deletion report is skipped."
fi

# Clean up rsync log file
rm -f "\$RSYNC_LOG_FILE"

echo -e "\n\${YELLOW}--- Directory and File Counts (Raw) ---\${NC}"
SOURCE_DIR_ACTUAL_COUNT=\$(find "\$SOURCE_DIR" -type d 2>/dev/null | wc -l)
SOURCE_FILE_ACTUAL_COUNT=\$(find "\$SOURCE_DIR" -type f 2>/dev/null | wc -l)
echo -e "\${YELLOW}Source Directory (\${SOURCE_DIR}):\${NC}"
echo -e "  Total Directories: \${SOURCE_DIR_ACTUAL_COUNT}"
echo -e "  Total Files:     \${SOURCE_FILE_ACTUAL_COUNT}"

TARGET_DIR_ACTUAL_COUNT=\$(find "\$TARGET_DIR" -type d 2>/dev/null | wc -l)
TARGET_FILE_ACTUAL_COUNT=\$(find "\$TARGET_DIR" -type f 2>/dev/null | wc -l)
echo -e "\n\${YELLOW}Target Directory (\${TARGET_DIR}):\${NC}"
echo -e "  Total Directories: \${TARGET_DIR_ACTUAL_COUNT}"
echo -e "  Total Files:     \${TARGET_FILE_ACTUAL_COUNT}"

echo -e "\n\${GREEN}Synchronization script finished at \$(date)\${NC}"
if [ "\$SYNC_SUCCESS" = true ]; then
    echo -e "\${YELLOW}Target directory \${TARGET_DIR} has been synchronized with \${SOURCE_DIR}.\${NC}"
else
    echo -e "\${RED}Synchronization incomplete due to errors.\${NC}"
fi