502 lines
19 KiB
Bash
502 lines
19 KiB
Bash
#!/bin/bash
|
|
|
|
# ─── Config ───────────────────────────────────────────────────────────────────
|
|
CONFIG_DIR="$HOME/.config/backup_project"
|
|
INSTALL_PATH="/usr/local/bin/backup_project"
|
|
|
|
# ─── Help ─────────────────────────────────────────────────────────────────────
|
|
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
cat <<EOF
|
|
|
|
backup_project — Incremental folder backup with versioned naming
|
|
|
|
USAGE:
|
|
backup_project [folder] Back up a folder (or current dir)
|
|
backup_project --set-version X.Y.Z [folder] Set the next version number (respects existing folders)
|
|
backup_project --force X.Y.Z [folder] Force exact version number (ignores existing folders, one-time)
|
|
backup_project --install Install script system-wide to /usr/local/bin
|
|
backup_project --help Show this help message
|
|
|
|
EXAMPLES:
|
|
backup_project # backs up current directory
|
|
backup_project ~/Documents/this-project # backs up specified folder
|
|
backup_project --set-version 2.0.15 # next backup will be 2.0.15 (or higher if folders exist)
|
|
backup_project --force 2.0.15 # next backup will be exactly 2.0.15
|
|
backup_project --force 2.0.15 ~/Documents/this-project
|
|
|
|
NOTES:
|
|
- On first run for any folder, you will be prompted for a starting version (e.g. 2.0.12)
|
|
- Each folder has its own config stored in ~/.config/backup_project/
|
|
- Backups are created in the same parent directory as the source folder
|
|
- To reset a folder's config: rm ~/.config/backup_project/<config>.cfg
|
|
- To view all configs: ls ~/.config/backup_project/
|
|
- To uninstall: sudo rm /usr/local/bin/backup_project
|
|
|
|
EOF
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Self-install ─────────────────────────────────────────────────────────────
|
|
if [[ "$1" == "--install" ]]; then
|
|
echo "Installing backup_project to $INSTALL_PATH ..."
|
|
sudo cp "$0" "$INSTALL_PATH"
|
|
sudo chmod +x "$INSTALL_PATH"
|
|
echo "Done! You can now run 'backup_project [folder]' from anywhere."
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Set version override ─────────────────────────────────────────────────────
|
|
# Usage: backup_project --set-version 2.0.15 [folder]
|
|
if [[ "$1" == "--set-version" ]]; then
|
|
NEW_VERSION="$2"
|
|
SOURCE="$(realpath "${3:-$(pwd)}")"
|
|
|
|
if ! echo "$NEW_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+
|
|
# If no argument given, use current directory
|
|
if [ -z "$1" ]; then
|
|
SOURCE="$(pwd)"
|
|
else
|
|
SOURCE="$1"
|
|
fi
|
|
|
|
# Strip trailing slash, resolve to absolute path
|
|
SOURCE="$(realpath "${SOURCE%/}")"
|
|
|
|
if [ ! -d "$SOURCE" ]; then
|
|
echo "Error: '$SOURCE' is not a directory."
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Load or create config for this source folder ────────────────────────────
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "First time backing up '$(basename "$SOURCE")'."
|
|
read -rp "Enter starting version (e.g. 2.0.12): " FULL_VERSION
|
|
|
|
# Validate format: must be X.Y.Z (digits and dots, at least one dot, ends in digits)
|
|
if ! echo "$FULL_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+$'; then
|
|
echo "Error: version must be in format like 2.0.12 or 1.0.0"
|
|
exit 1
|
|
fi
|
|
|
|
# Split into prefix (everything before last dot) and starting minor (last number)
|
|
BASE_VERSION="${FULL_VERSION%.*}" # e.g. 2.0
|
|
START_MINOR="${FULL_VERSION##*.}" # e.g. 12
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "Saved: prefix='$BASE_VERSION', starting minor='$START_MINOR' for '$(basename "$SOURCE")'."
|
|
else
|
|
source "$FOLDER_CONFIG"
|
|
fi
|
|
|
|
# ─── Find next version number ─────────────────────────────────────────────────
|
|
BASE_NAME=$(basename "$SOURCE")
|
|
PARENT_DIR=$(dirname "$SOURCE")
|
|
|
|
if [ -n "$FORCE_MINOR" ]; then
|
|
# --force: use exactly this number, ignore existing folders, then clear the force
|
|
NEXT="$FORCE_MINOR"
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$FORCE_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "FORCE_MINOR=" >> "$FOLDER_CONFIG"
|
|
else
|
|
# Find highest existing minor version >= START_MINOR
|
|
LAST=$(ls -d "${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}".* 2>/dev/null \
|
|
| grep -oP '\d+
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|
|
; then
|
|
echo "Error: version must be in format like 2.0.15"
|
|
exit 1
|
|
fi
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "Error: no config found for '$SOURCE'. Run a backup first."
|
|
exit 1
|
|
fi
|
|
|
|
BASE_VERSION="${NEW_VERSION%.*}"
|
|
START_MINOR="${NEW_VERSION##*.}"
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "FORCE_MINOR=" >> "$FOLDER_CONFIG"
|
|
echo "✓ Next backup of '$(basename "$SOURCE")' will be '$NEW_VERSION'"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Force version override ───────────────────────────────────────────────────
|
|
# Usage: backup_project --force 2.0.15 [folder]
|
|
if [[ "$1" == "--force" ]]; then
|
|
NEW_VERSION="$2"
|
|
SOURCE="$(realpath "${3:-$(pwd)}")"
|
|
|
|
if ! echo "$NEW_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+
|
|
|
|
# ─── Resolve source folder ────────────────────────────────────────────────────
|
|
# If no argument given, use current directory
|
|
if [ -z "$1" ]; then
|
|
SOURCE="$(pwd)"
|
|
else
|
|
SOURCE="$1"
|
|
fi
|
|
|
|
# Strip trailing slash, resolve to absolute path
|
|
SOURCE="$(realpath "${SOURCE%/}")"
|
|
|
|
if [ ! -d "$SOURCE" ]; then
|
|
echo "Error: '$SOURCE' is not a directory."
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Load or create config for this source folder ────────────────────────────
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "First time backing up '$(basename "$SOURCE")'."
|
|
read -rp "Enter starting version (e.g. 2.0.12): " FULL_VERSION
|
|
|
|
# Validate format: must be X.Y.Z (digits and dots, at least one dot, ends in digits)
|
|
if ! echo "$FULL_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+$'; then
|
|
echo "Error: version must be in format like 2.0.12 or 1.0.0"
|
|
exit 1
|
|
fi
|
|
|
|
# Split into prefix (everything before last dot) and starting minor (last number)
|
|
BASE_VERSION="${FULL_VERSION%.*}" # e.g. 2.0
|
|
START_MINOR="${FULL_VERSION##*.}" # e.g. 12
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "Saved: prefix='$BASE_VERSION', starting minor='$START_MINOR' for '$(basename "$SOURCE")'."
|
|
else
|
|
source "$FOLDER_CONFIG"
|
|
fi
|
|
|
|
# ─── Find next version number ─────────────────────────────────────────────────
|
|
BASE_NAME=$(basename "$SOURCE")
|
|
PARENT_DIR=$(dirname "$SOURCE")
|
|
|
|
# Find highest existing minor version, but only consider numbers >= START_MINOR
|
|
LAST=$(ls -d "${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}".* 2>/dev/null \
|
|
| grep -oP '\d+$' \
|
|
| awk -v start="$START_MINOR" '$1 >= start' \
|
|
| sort -n \
|
|
| tail -1)
|
|
|
|
if [ -z "$LAST" ]; then
|
|
NEXT="$START_MINOR"
|
|
else
|
|
NEXT=$((LAST + 1))
|
|
fi
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|
|
; then
|
|
echo "Error: version must be in format like 2.0.15"
|
|
exit 1
|
|
fi
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "Error: no config found for '$SOURCE'. Run a backup first."
|
|
exit 1
|
|
fi
|
|
|
|
BASE_VERSION="${NEW_VERSION%.*}"
|
|
FORCE_MINOR="${NEW_VERSION##*.}"
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$FORCE_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "FORCE_MINOR=$FORCE_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "✓ Next backup of '$(basename "$SOURCE")' will be forced to '$NEW_VERSION' (ignoring existing folders)"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Resolve source folder ────────────────────────────────────────────────────
|
|
# If no argument given, use current directory
|
|
if [ -z "$1" ]; then
|
|
SOURCE="$(pwd)"
|
|
else
|
|
SOURCE="$1"
|
|
fi
|
|
|
|
# Strip trailing slash, resolve to absolute path
|
|
SOURCE="$(realpath "${SOURCE%/}")"
|
|
|
|
if [ ! -d "$SOURCE" ]; then
|
|
echo "Error: '$SOURCE' is not a directory."
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Load or create config for this source folder ────────────────────────────
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "First time backing up '$(basename "$SOURCE")'."
|
|
read -rp "Enter starting version (e.g. 2.0.12): " FULL_VERSION
|
|
|
|
# Validate format: must be X.Y.Z (digits and dots, at least one dot, ends in digits)
|
|
if ! echo "$FULL_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+$'; then
|
|
echo "Error: version must be in format like 2.0.12 or 1.0.0"
|
|
exit 1
|
|
fi
|
|
|
|
# Split into prefix (everything before last dot) and starting minor (last number)
|
|
BASE_VERSION="${FULL_VERSION%.*}" # e.g. 2.0
|
|
START_MINOR="${FULL_VERSION##*.}" # e.g. 12
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "Saved: prefix='$BASE_VERSION', starting minor='$START_MINOR' for '$(basename "$SOURCE")'."
|
|
else
|
|
source "$FOLDER_CONFIG"
|
|
fi
|
|
|
|
# ─── Find next version number ─────────────────────────────────────────────────
|
|
BASE_NAME=$(basename "$SOURCE")
|
|
PARENT_DIR=$(dirname "$SOURCE")
|
|
|
|
# Find highest existing minor version, but only consider numbers >= START_MINOR
|
|
LAST=$(ls -d "${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}".* 2>/dev/null \
|
|
| grep -oP '\d+$' \
|
|
| awk -v start="$START_MINOR" '$1 >= start' \
|
|
| sort -n \
|
|
| tail -1)
|
|
|
|
if [ -z "$LAST" ]; then
|
|
NEXT="$START_MINOR"
|
|
else
|
|
NEXT=$((LAST + 1))
|
|
fi
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|
|
\
|
|
| awk -v start="$START_MINOR" '$1 >= start' \
|
|
| sort -n \
|
|
| tail -1)
|
|
|
|
if [ -z "$LAST" ]; then
|
|
NEXT="$START_MINOR"
|
|
else
|
|
NEXT=$((LAST + 1))
|
|
fi
|
|
fi
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|
|
; then
|
|
echo "Error: version must be in format like 2.0.15"
|
|
exit 1
|
|
fi
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "Error: no config found for '$SOURCE'. Run a backup first."
|
|
exit 1
|
|
fi
|
|
|
|
BASE_VERSION="${NEW_VERSION%.*}"
|
|
START_MINOR="${NEW_VERSION##*.}"
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "FORCE_MINOR=" >> "$FOLDER_CONFIG"
|
|
echo "✓ Next backup of '$(basename "$SOURCE")' will be '$NEW_VERSION'"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Force version override ───────────────────────────────────────────────────
|
|
# Usage: backup_project --force 2.0.15 [folder]
|
|
if [[ "$1" == "--force" ]]; then
|
|
NEW_VERSION="$2"
|
|
SOURCE="$(realpath "${3:-$(pwd)}")"
|
|
|
|
if ! echo "$NEW_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+
|
|
|
|
# ─── Resolve source folder ────────────────────────────────────────────────────
|
|
# If no argument given, use current directory
|
|
if [ -z "$1" ]; then
|
|
SOURCE="$(pwd)"
|
|
else
|
|
SOURCE="$1"
|
|
fi
|
|
|
|
# Strip trailing slash, resolve to absolute path
|
|
SOURCE="$(realpath "${SOURCE%/}")"
|
|
|
|
if [ ! -d "$SOURCE" ]; then
|
|
echo "Error: '$SOURCE' is not a directory."
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Load or create config for this source folder ────────────────────────────
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "First time backing up '$(basename "$SOURCE")'."
|
|
read -rp "Enter starting version (e.g. 2.0.12): " FULL_VERSION
|
|
|
|
# Validate format: must be X.Y.Z (digits and dots, at least one dot, ends in digits)
|
|
if ! echo "$FULL_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+$'; then
|
|
echo "Error: version must be in format like 2.0.12 or 1.0.0"
|
|
exit 1
|
|
fi
|
|
|
|
# Split into prefix (everything before last dot) and starting minor (last number)
|
|
BASE_VERSION="${FULL_VERSION%.*}" # e.g. 2.0
|
|
START_MINOR="${FULL_VERSION##*.}" # e.g. 12
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "Saved: prefix='$BASE_VERSION', starting minor='$START_MINOR' for '$(basename "$SOURCE")'."
|
|
else
|
|
source "$FOLDER_CONFIG"
|
|
fi
|
|
|
|
# ─── Find next version number ─────────────────────────────────────────────────
|
|
BASE_NAME=$(basename "$SOURCE")
|
|
PARENT_DIR=$(dirname "$SOURCE")
|
|
|
|
# Find highest existing minor version, but only consider numbers >= START_MINOR
|
|
LAST=$(ls -d "${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}".* 2>/dev/null \
|
|
| grep -oP '\d+$' \
|
|
| awk -v start="$START_MINOR" '$1 >= start' \
|
|
| sort -n \
|
|
| tail -1)
|
|
|
|
if [ -z "$LAST" ]; then
|
|
NEXT="$START_MINOR"
|
|
else
|
|
NEXT=$((LAST + 1))
|
|
fi
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|
|
; then
|
|
echo "Error: version must be in format like 2.0.15"
|
|
exit 1
|
|
fi
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "Error: no config found for '$SOURCE'. Run a backup first."
|
|
exit 1
|
|
fi
|
|
|
|
BASE_VERSION="${NEW_VERSION%.*}"
|
|
FORCE_MINOR="${NEW_VERSION##*.}"
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$FORCE_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "FORCE_MINOR=$FORCE_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "✓ Next backup of '$(basename "$SOURCE")' will be forced to '$NEW_VERSION' (ignoring existing folders)"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── Resolve source folder ────────────────────────────────────────────────────
|
|
# If no argument given, use current directory
|
|
if [ -z "$1" ]; then
|
|
SOURCE="$(pwd)"
|
|
else
|
|
SOURCE="$1"
|
|
fi
|
|
|
|
# Strip trailing slash, resolve to absolute path
|
|
SOURCE="$(realpath "${SOURCE%/}")"
|
|
|
|
if [ ! -d "$SOURCE" ]; then
|
|
echo "Error: '$SOURCE' is not a directory."
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Load or create config for this source folder ────────────────────────────
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
CONFIG_KEY=$(echo "$SOURCE" | tr '/' '_' | tr ' ' '_')
|
|
FOLDER_CONFIG="$CONFIG_DIR/${CONFIG_KEY}.cfg"
|
|
|
|
if [ ! -f "$FOLDER_CONFIG" ]; then
|
|
echo "First time backing up '$(basename "$SOURCE")'."
|
|
read -rp "Enter starting version (e.g. 2.0.12): " FULL_VERSION
|
|
|
|
# Validate format: must be X.Y.Z (digits and dots, at least one dot, ends in digits)
|
|
if ! echo "$FULL_VERSION" | grep -qP '^\d+(\.\d+)*\.\d+$'; then
|
|
echo "Error: version must be in format like 2.0.12 or 1.0.0"
|
|
exit 1
|
|
fi
|
|
|
|
# Split into prefix (everything before last dot) and starting minor (last number)
|
|
BASE_VERSION="${FULL_VERSION%.*}" # e.g. 2.0
|
|
START_MINOR="${FULL_VERSION##*.}" # e.g. 12
|
|
|
|
echo "BASE_VERSION=$BASE_VERSION" > "$FOLDER_CONFIG"
|
|
echo "START_MINOR=$START_MINOR" >> "$FOLDER_CONFIG"
|
|
echo "Saved: prefix='$BASE_VERSION', starting minor='$START_MINOR' for '$(basename "$SOURCE")'."
|
|
else
|
|
source "$FOLDER_CONFIG"
|
|
fi
|
|
|
|
# ─── Find next version number ─────────────────────────────────────────────────
|
|
BASE_NAME=$(basename "$SOURCE")
|
|
PARENT_DIR=$(dirname "$SOURCE")
|
|
|
|
# Find highest existing minor version, but only consider numbers >= START_MINOR
|
|
LAST=$(ls -d "${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}".* 2>/dev/null \
|
|
| grep -oP '\d+$' \
|
|
| awk -v start="$START_MINOR" '$1 >= start' \
|
|
| sort -n \
|
|
| tail -1)
|
|
|
|
if [ -z "$LAST" ]; then
|
|
NEXT="$START_MINOR"
|
|
else
|
|
NEXT=$((LAST + 1))
|
|
fi
|
|
|
|
DEST="${PARENT_DIR}/${BASE_NAME}-${BASE_VERSION}.${NEXT}"
|
|
|
|
# ─── Copy ─────────────────────────────────────────────────────────────────────
|
|
cp -r "$SOURCE" "$DEST"
|
|
echo "✓ Backed up '$(basename "$SOURCE")' → '$DEST'"
|