Skip to content

Instantly share code, notes, and snippets.

@DanijelMi
Last active May 22, 2019 21:49
Show Gist options
  • Save DanijelMi/9d5412aa3e76c6d9f1073f0401e0828b to your computer and use it in GitHub Desktop.
Save DanijelMi/9d5412aa3e76c6d9f1073f0401e0828b to your computer and use it in GitHub Desktop.
A cron-managed script used for performing incremental backups.
#!/usr/bin/env bash
# Author: Danijel Milosevic
# No warranty, use at your own risk.
# How many snapshots to keep before starting to delete the old ones
SNAPSHOT_COUNT=15
# A list of absolute paths to backup.
INCLUDE_PATHS=("$HOME/Desktop/RSYNC/F1/")
# Overwrite if an arg was given
[ -z "$1" ] || INCLUDE_PATHS=$1
# Absolute path to transfer destination
TARGET_PATH="$HOME/Desktop/RSYNC/F2"
# Overwrite if an arg was given
[ -z "$2" ] || TARGET_PATH=$2
# A list of folder names and files to exclude.
EXCLUDE_PATHS=(
)
# Build proper rsync args from INCLUDE_PATHS array
for item in "${INCLUDE_PATHS[@]}"; do
INCLUDE_ARGS="${INCLUDE_ARGS} ${item}"
done
# Build proper rsync args from EXCLUDE_PATHS array
for item in "${EXCLUDE_PATHS[@]}"; do
EXCLUDE_FLAGS="${EXCLUDE_FLAGS} --exclude=${item}"
done
# Delete the oldest snapshot
if [ -d $TARGET_PATH.$SNAPSHOT_COUNT ]; then
rm -rf $TARGET_PATH.$SNAPSHOT_COUNT
fi
# Rename existing snapshots 1 number higher
for (( i=$SNAPSHOT_COUNT; i>0; i-- )); do
if [ -d $TARGET_PATH.$(($i - 1)) ]; then
mv $TARGET_PATH.$(($i - 1)) $TARGET_PATH.$i
# Special case for the latest backup dir, since it doesn't have a digit appended
elif [ $i -eq 1 ] && [ -d $TARGET_PATH ]; then
mv $TARGET_PATH $TARGET_PATH.$i
fi
done
# If a backup exists, save disk space by utilising hard links to existing files if they are identical as the new backup
if [ -d $TARGET_PATH.1 ]; then
RSYNC_ARGS=( --link-dest="$TARGET_PATH.1")
fi;
RSYNC_ARGS+=(
--recursive # Copy everything from subdirs
--links # Copy over symlinks
--hard-links # Copy over hard links
--perms # Preserve user perms
--times # Preserve time stamps
--group # Preserve file group
--checksum # Skips files based on checksum instead of datetime + size comparison. Better but slower
--owner # Preserve file owner
-D # Transfer special files like socket, device
--progress # Show transfer progress
#--partial # Keep partially transfered files
--update # Skip files that are newer on the receiver
--human-readable # Makes the transfer output more readable
#--relative # Use relative path names
--compress # Compress/decompress during transfer. Useful over network
--delete # Delete files in destination that don't exist in source
--log-file=$HOME/rsync.log # Store the logs in the home dir
#--dry-run # Disables rsync, just shows what would have been copied instead. Good for testing/debugging
${EXCLUDE_FLAGS} # Transfer blacklist
${INCLUDE_ARGS} # List of source directories
$TARGET_PATH # Target directory
)
rsync "${RSYNC_ARGS[@]}" # Actual execution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment