Skip to content

Instantly share code, notes, and snippets.

@kossoy
Last active October 7, 2025 17:58
Show Gist options
  • Select an option

  • Save kossoy/6ab78b54216645749700d958b88bea49 to your computer and use it in GitHub Desktop.

Select an option

Save kossoy/6ab78b54216645749700d958b88bea49 to your computer and use it in GitHub Desktop.
DJI Osmo Pocket 3 Backup & Wipe Scripts - Automated workflow for backing up DJI camera videos to dated folders with verification and cleanup
# DJI Backup Configuration File
# Copy this to ~/.dji_backup_config to customize settings
# Last Updated: October 7, 2025
# Source settings
SRC_VOLUME="/Volumes/DJI Osmo P3"
SRC_FOLDER="${SRC_VOLUME}/DCIM/DJI_001"
# Destination settings
DEST_BASE="/Volumes/Media/Videos/DJI Osmo Pocket 3"
# Scripts and files
VIDEO_LINKS_SCRIPT="${HOME}/bin/video_links.zsh"
HISTORY_FILE="${HOME}/.dji_backup_history"
# Features
ENABLE_NOTIFICATIONS=1 # 1 = enable macOS notifications, 0 = disable
ENABLE_CHECKSUM_VERIFY=0 # 1 = use checksums (slower), 0 = use size (faster)
# Custom rsync options (advanced)
# RSYNC_EXTRA_OPTS="--bwlimit=10000" # Limit bandwidth to 10MB/s

DJI Osmo Pocket 3 Backup & Wipe Scripts

Author: Oleg Kossoy [email protected]
Version: 2.0.0
Last Updated: October 7, 2025

A professional, automated workflow for backing up DJI Osmo Pocket 3 videos to organized dated folders with verification, cleanup, and intelligent error handling.

🎯 Overview

These scripts provide a complete solution for managing DJI camera backups:

  • wipe_dji.zsh - Main backup script that copies, verifies, wipes, and ejects
  • video_links.zsh - Creates convenient date-based symlinks for easy video access
  • .dji_backup_config.example - Configuration template

✨ Features

Safety & Reliability

  • File verification - Size or checksum-based validation
  • 🛡️ Smart error recovery - Never wipes source if copy fails
  • 🔄 Resume capability - Continues interrupted transfers
  • ⚠️ Dry-run mode - Preview operations before execution

User Experience

  • 🎨 Beautiful colored output - Clear status indicators
  • 📊 Progress tracking - Real-time transfer speeds and ETA
  • 🔔 macOS notifications - Alerts on completion or errors
  • 📈 Backup history - Track all operations with statistics

Flexibility

  • ⚙️ Configuration file - Customize all settings
  • 🔧 Command-line options - Override defaults per run
  • 📝 Verbose mode - Detailed debugging information

📋 Requirements

  • macOS (uses diskutil for disk management)
  • zsh (default on modern macOS)
  • rsync 3.4+ (via Homebrew for best features)

Installation

  1. Install modern rsync (recommended):

    brew install rsync
  2. Download the scripts:

    # Create bin directory if needed
    mkdir -p ~/bin
    
    # Download scripts
    curl -o ~/bin/wipe_dji.zsh https://gist.githubusercontent.com/kossoy/6ab78b54216645749700d958b88bea49/raw/wipe_dji.zsh
    curl -o ~/bin/video_links.zsh https://gist.githubusercontent.com/kossoy/6ab78b54216645749700d958b88bea49/raw/video_links.zsh
    
    # Make executable
    chmod +x ~/bin/wipe_dji.zsh ~/bin/video_links.zsh
  3. Optional: Create configuration file:

    curl -o ~/.dji_backup_config https://gist.githubusercontent.com/kossoy/6ab78b54216645749700d958b88bea49/raw/.dji_backup_config.example
    # Edit with your preferred paths
    nano ~/.dji_backup_config

🚀 Usage

Basic Usage

Connect your DJI Osmo Pocket 3 and run:

~/bin/wipe_dji.zsh

This will:

  1. Copy all videos from the camera to dated folder (e.g., 2025/10/07)
  2. Verify all files were copied correctly
  3. Delete files from the camera
  4. Eject the disk safely
  5. Update symlinks for easy access

Command-Line Options

# Preview what will happen (no changes made)
~/bin/wipe_dji.zsh --dry-run

# Copy files but don't wipe the source
~/bin/wipe_dji.zsh --no-wipe

# Use checksum verification (slower but thorough)
~/bin/wipe_dji.zsh --checksum

# View backup statistics
~/bin/wipe_dji.zsh --stats

# Enable verbose debug output
~/bin/wipe_dji.zsh --verbose

# Show help
~/bin/wipe_dji.zsh --help

Configuration

Create ~/.dji_backup_config to customize:

# Source settings
SRC_VOLUME="/Volumes/DJI Osmo P3"
SRC_FOLDER="${SRC_VOLUME}/DCIM/DJI_001"

# Destination settings
DEST_BASE="/Volumes/Media/Videos/DJI Osmo Pocket 3"

# Features
ENABLE_NOTIFICATIONS=1          # macOS notifications
ENABLE_CHECKSUM_VERIFY=0        # Use checksums (slower)

📁 Directory Structure

The script organizes videos by date:

/Volumes/Media/Videos/DJI Osmo Pocket 3/
├── 2025/
│   ├── 10/
│   │   ├── 01/
│   │   │   ├── DJI_20251001175635_0001_D.MP4
│   │   │   └── DJI_20251001180245_0002_D.MP4
│   │   └── 07/
│   │       └── DJI_20251007145532_0001_D.MP4

Symlinks (created by video_links.zsh)

/Volumes/Media/DJI Folders/
├── Today -> /Volumes/Media/Videos/DJI Osmo Pocket 3/2025/10/07
└── 2025-10/
    ├── 01-DJI_20251001175635_0001_D.MP4
    ├── 01-DJI_20251001180245_0002_D.MP4
    └── 07-DJI_20251007145532_0001_D.MP4

📊 Backup History

The script maintains a history log at ~/.dji_backup_history:

# View statistics
~/bin/wipe_dji.zsh --stats

Example output:

📊 Recent Backup History
Total backups recorded: 15

Last 10 backups:
  ✅ 2025-10-07 20:17:38 - 2 files - 1.3G - 25s
  ✅ 2025-10-05 14:32:15 - 5 files - 3.2G - 68s
  ✅ 2025-10-03 09:45:22 - 1 files - 184M - 6s

🔔 Notifications

The script sends macOS notifications on:

  • ✅ Successful backup completion
  • ❌ Errors or failures
  • ⚠️ Important warnings

🛡️ Safety Features

Error Handling

  • Copy failures - Source files are preserved
  • Verification failures - Source is NOT wiped
  • Interrupted operations - Graceful cleanup and error messages
  • Ctrl+C handling - Safe cancellation at any point

Verification Methods

Size-based (default, fast):

  • Compares file sizes between source and destination
  • Quick verification suitable for most use cases

Checksum-based (optional, thorough):

~/bin/wipe_dji.zsh --checksum
  • Compares actual file content using checksums
  • Slower but guarantees bit-perfect copies
  • Recommended for critical footage

🎬 Example Session

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📹 DJI Osmo Pocket 3 Backup & Wipe
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2025-10-07 20:17:38
Host: MacBook-Pro

ℹ️  Checking paths...

ℹ️  Source:      /Volumes/DJI Osmo P3/DCIM/DJI_001
ℹ️  Destination: /Volumes/Media/Videos/DJI Osmo Pocket 3/2025/10/07
ℹ️  Files:       2 (1.3G)
ℹ️  Verification: Size comparison (fast)

⚠️  This will:
  1. Copy files from DJI to /Volumes/Media/Videos/DJI Osmo Pocket 3/2025/10/07
  2. Delete ALL FILES from /Volumes/DJI Osmo P3
  3. Eject the disk

ℹ️  Creating destination directory...
ℹ️  Copying files with progress (excluding .LRF files)...

       1.23G  45%  42.89MB/s    0:00:25

✅ Files copied successfully
ℹ️  Verifying: 2/2 files
✅ Verification passed: 2 of 2 files verified
⚠️  Deleting all files from /Volumes/DJI Osmo P3...
✅ Volume wiped
ℹ️  Attempting to eject /Volumes/DJI Osmo P3...
✅ Volume ejected successfully
ℹ️  Updating video folder symlinks...
✅ Symlink update complete

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Backup Complete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Files saved to: /Volumes/Media/Videos/DJI Osmo Pocket 3/2025/10/07
✅ Total files: 2 (1.3G)
✅ Duration: 25s

🔧 Troubleshooting

Script says rsync failed

Solution: Install the latest rsync via Homebrew:

brew install rsync

No notifications appearing

Solution: Enable notifications in config:

echo "ENABLE_NOTIFICATIONS=1" >> ~/.dji_backup_config

Source volume not found

Solution: Check if camera is mounted and update config:

diskutil list  # Find your DJI volume name

📝 License

MIT License - Feel free to use and modify for your needs.

🤝 Contributing

Suggestions and improvements welcome! Open an issue or submit a pull request.

📧 Contact

Oleg Kossoy
Email: [email protected]
GitHub: @kossoy


⭐ If you find these scripts useful, please star the gist!

#!/usr/bin/env zsh
# DJI Osmo Pocket 3 Backup and Wipe Script
# Copies videos from DJI camera to dated folder, then wipes the card
#
# Author: Oleg Kossoy <[email protected]>
# Version: 2.0.0
# Last Updated: October 7, 2025
set -euo pipefail
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Load configuration file if it exists
CONFIG_FILE="${HOME}/.dji_backup_config"
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
fi
# Default configuration (can be overridden in config file)
: ${SRC_VOLUME:="/Volumes/DJI Osmo P3"}
: ${SRC_FOLDER:="${SRC_VOLUME}/DCIM/DJI_001"}
: ${DEST_BASE:="/Volumes/Media/Videos/DJI Osmo Pocket 3"}
: ${VIDEO_LINKS_SCRIPT:="${HOME}/bin/video_links.zsh"}
: ${HISTORY_FILE:="${HOME}/.dji_backup_history"}
: ${ENABLE_NOTIFICATIONS:=1}
: ${ENABLE_CHECKSUM_VERIFY:=0} # Slower but more thorough
TIMESTAMP=$(date "+%Y/%m/%d")
DEST_FOLDER="${DEST_BASE}/${TIMESTAMP}"
# Use Homebrew rsync (3.4.1) for better progress and features
RSYNC_BIN="/opt/homebrew/bin/rsync"
if [[ ! -x "$RSYNC_BIN" ]]; then
# Fallback to system rsync if Homebrew version not available
RSYNC_BIN="rsync"
fi
# Runtime flags
DRY_RUN=0
SKIP_WIPE=0
VERBOSE=0
# Colors for terminal output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
PURPLE='\033[0;35m'
NC='\033[0m' # No Color
# -----------------------------------------------------------------------------
# Error Handling
# -----------------------------------------------------------------------------
OPERATION_STARTED=0
COPY_COMPLETED=0
error_handler() {
local exit_code=$1
local line_no=$2
echo ""
log_error "Error on line ${line_no} (exit code: ${exit_code})"
if [[ $COPY_COMPLETED -eq 1 ]]; then
log_warning "Files were copied successfully but an error occurred during cleanup"
log_info "Source files NOT deleted for safety"
elif [[ $OPERATION_STARTED -eq 1 ]]; then
log_warning "Operation interrupted - source files preserved"
log_info "You may need to manually check: ${DEST_FOLDER}"
fi
# Send error notification
if [[ $ENABLE_NOTIFICATIONS -eq 1 ]]; then
osascript -e "display notification \"Backup failed - check terminal\" with title \"❌ DJI Backup Error\" sound name \"Basso\"" 2>/dev/null || true
fi
exit "$exit_code"
}
trap 'error_handler $? $LINENO' ERR
trap 'log_warning "Operation cancelled by user"; exit 130' INT TERM
# -----------------------------------------------------------------------------
# Utility Functions
# -----------------------------------------------------------------------------
print_header() {
local title="$1"
echo ""
echo "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo "${CYAN}${title}${NC}"
echo "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
}
log_info() {
echo "${BLUE}ℹ️ ${1}${NC}"
}
log_success() {
echo "${GREEN}${1}${NC}"
}
log_warning() {
echo "${YELLOW}⚠️ ${1}${NC}"
}
log_error() {
echo "${RED}${1}${NC}" >&2
}
log_debug() {
if [[ $VERBOSE -eq 1 ]]; then
echo "${PURPLE}[DEBUG] ${1}${NC}"
fi
}
show_usage() {
cat << EOF
${CYAN}DJI Osmo Pocket 3 Backup & Wipe Script${NC}
Usage: $(basename "$0") [OPTIONS]
Options:
--dry-run Show what would be done without making changes
--no-wipe Copy and verify files but don't wipe the source
--checksum Use checksum verification (slower but thorough)
--stats Show backup statistics before running
--verbose, -v Enable verbose debug output
--help, -h Show this help message
Examples:
$(basename "$0") # Normal operation
$(basename "$0") --dry-run # Preview what will happen
$(basename "$0") --no-wipe # Copy only, don't delete source
$(basename "$0") --checksum # Use checksums for verification
Configuration:
Config file: ${CONFIG_FILE}
History file: ${HISTORY_FILE}
EOF
}
# -----------------------------------------------------------------------------
# History & Statistics Functions
# -----------------------------------------------------------------------------
log_to_history() {
local operation_status="$1"
local file_count="$2"
local total_size="$3"
local duration="$4"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp}|${operation_status}|${file_count}|${total_size}|${duration}s|${DEST_FOLDER}" >> "$HISTORY_FILE"
}
show_statistics() {
if [[ ! -f "$HISTORY_FILE" ]]; then
log_info "No backup history found"
return
fi
print_header "📊 Recent Backup History"
local total_backups=$(wc -l < "$HISTORY_FILE" | tr -d ' ')
log_info "Total backups recorded: ${total_backups}"
echo ""
echo "${CYAN}Last 10 backups:${NC}"
tail -10 "$HISTORY_FILE" | while IFS='|' read -r date operation_status files size duration dest; do
local status_icon=""
local color=$GREEN
if [[ "$operation_status" == "ERROR" ]]; then
status_icon=""
color=$RED
elif [[ "$operation_status" == "DRY_RUN" ]]; then
status_icon="🔍"
color=$BLUE
fi
printf " ${color}%s${NC} %s - %s files - %s - %ss\n" "$status_icon" "$date" "$files" "$size" "$duration"
done
echo ""
}
send_notification() {
local title="$1"
local message="$2"
local sound="${3:-Glass}"
if [[ $ENABLE_NOTIFICATIONS -eq 1 ]]; then
osascript -e "display notification \"${message}\" with title \"${title}\" sound name \"${sound}\"" 2>/dev/null || true
fi
}
# -----------------------------------------------------------------------------
# Validation Functions
# -----------------------------------------------------------------------------
check_paths() {
local has_error=0
if [[ ! -d "$SRC_VOLUME" ]]; then
log_error "Source volume not found: ${SRC_VOLUME}"
log_info "Is the Osmo Pocket 3 connected?"
has_error=1
fi
if [[ ! -d "$SRC_FOLDER" ]]; then
log_error "Source folder not found: ${SRC_FOLDER}"
has_error=1
fi
if [[ ! -d "$DEST_BASE" ]]; then
log_warning "Destination base does not exist. Creating it..."
if [[ $DRY_RUN -eq 0 ]]; then
mkdir -p "$DEST_BASE" || {
log_error "Failed to create ${DEST_BASE}"
has_error=1
}
fi
fi
return $has_error
}
count_files() {
local dir="$1"
# Exclude .LRF and ._ (AppleDouble/metadata) files from count
local count=$(find "$dir" -type f -not -name "*.LRF" -not -name "._*" 2>/dev/null | wc -l | tr -d ' ')
echo "$count"
}
get_total_size() {
local dir="$1"
du -sh "$dir" 2>/dev/null | cut -f1
}
# -----------------------------------------------------------------------------
# Main Process Functions
# -----------------------------------------------------------------------------
copy_files() {
log_info "Creating destination directory: ${DEST_FOLDER}"
if [[ $DRY_RUN -eq 0 ]]; then
mkdir -p "$DEST_FOLDER" || {
log_error "Failed to create destination folder"
exit 5
}
fi
if [[ $DRY_RUN -eq 1 ]]; then
log_warning "DRY RUN: Would copy files from ${SRC_FOLDER} to ${DEST_FOLDER}"
echo ""
"$RSYNC_BIN" -ahn --info=progress2 --no-inc-recursive --exclude='*.LRF' "$SRC_FOLDER/" "$DEST_FOLDER/" || true
echo ""
log_info "DRY RUN: No files were actually copied"
return 0
fi
log_info "Copying files with progress (excluding .LRF files)..."
echo ""
# Use modern rsync with better progress display and resume capability
# --info=progress2: Single-line progress with overall stats
# -h: Human-readable sizes
# -a: Archive mode (preserves permissions, times, etc.)
# --no-inc-recursive: More accurate progress for large directories
# --partial: Keep partially transferred files (enables resume)
# --partial-dir: Store partial files in hidden directory
"$RSYNC_BIN" -ah --info=progress2 --no-inc-recursive \
--partial --partial-dir=.rsync-partial \
--exclude='*.LRF' "$SRC_FOLDER/" "$DEST_FOLDER/" || {
log_error "Copy failed! Aborting."
exit 5
}
echo ""
log_success "Files copied successfully"
}
verify_copy() {
if [[ $ENABLE_CHECKSUM_VERIFY -eq 1 ]]; then
verify_copy_checksum
return $?
else
verify_copy_size
return $?
fi
}
verify_copy_size() {
log_info "Verifying copied files (size comparison)..."
local all_verified=0
local verified_count=0
local total_count=0
# Check that each source file exists in destination with matching size
while IFS= read -r src_file; do
((total_count++))
local filename=$(basename "$src_file")
local dest_file="${DEST_FOLDER}/${filename}"
# Show progress
printf "\r${BLUE}ℹ️ Verifying: ${verified_count}/${total_count} files${NC}"
if [[ ! -f "$dest_file" ]]; then
echo "" # newline after progress
log_error "Missing file: ${filename}"
all_verified=1
else
# Compare file sizes
local src_size=$(stat -f%z "$src_file" 2>/dev/null || stat -c%s "$src_file")
local dest_size=$(stat -f%z "$dest_file" 2>/dev/null || stat -c%s "$dest_file")
if [[ "$src_size" -eq "$dest_size" ]]; then
((verified_count++))
else
echo "" # newline after progress
log_error "Size mismatch for ${filename}: source=${src_size}, dest=${dest_size}"
all_verified=1
fi
fi
done < <(find "$SRC_FOLDER" -type f -not -name "*.LRF" -not -name "._*" 2>/dev/null)
echo "" # newline after progress
if [[ $all_verified -eq 0 && $verified_count -eq $total_count ]]; then
log_success "Verification passed: ${verified_count} of ${total_count} files verified"
return 0
else
log_error "Verification failed! Only ${verified_count} of ${total_count} files verified successfully"
return 1
fi
}
verify_copy_checksum() {
log_info "Verifying copied files (checksum comparison - this may take a while)..."
echo ""
# Use rsync's built-in checksum verification
# -c: skip based on checksum, not mod-time & size
# -n: dry-run (just compare, don't copy)
local diff_output=$("$RSYNC_BIN" -ahn --checksum --exclude='*.LRF' "$SRC_FOLDER/" "$DEST_FOLDER/" 2>&1)
# Filter out rsync status messages
local files_differ=$(echo "$diff_output" | grep -v "sending incremental file list" | grep -v "^$" | grep -v "sent " | grep -v "total size")
if [[ -z "$files_differ" ]]; then
log_success "Checksum verification passed: All files match exactly"
return 0
else
log_error "Checksum verification failed! Files differ:"
echo "$files_differ" | sed 's/^/ /'
return 1
fi
}
wipe_volume() {
if [[ $DRY_RUN -eq 1 ]]; then
log_warning "DRY RUN: Would delete all files from ${SRC_VOLUME}"
return 0
fi
if [[ $SKIP_WIPE -eq 1 ]]; then
log_warning "SKIP: Not wiping source volume (--no-wipe flag)"
return 0
fi
log_warning "Deleting all files from ${SRC_VOLUME}..."
# This won't touch the mount point itself or special '.' and '..'
rm -rf "$SRC_VOLUME/"* "$SRC_VOLUME/".* 2>/dev/null
log_success "Volume wiped"
}
eject_volume() {
if [[ $DRY_RUN -eq 1 ]]; then
log_warning "DRY RUN: Would eject ${SRC_VOLUME}"
return 0
fi
if [[ $SKIP_WIPE -eq 1 ]]; then
log_info "SKIP: Not ejecting volume (--no-wipe flag)"
return 0
fi
log_info "Getting device identifier..."
local device_id=$(diskutil info "$SRC_VOLUME" 2>/dev/null | awk -F': *' '/Device Node/ {print $2}')
if [[ -z "$device_id" ]]; then
log_error "Could not determine device node for ${SRC_VOLUME}"
return 10
fi
log_info "Device: ${device_id}"
log_info "Attempting to eject ${SRC_VOLUME}..."
# Try a normal eject first
if diskutil eject "$SRC_VOLUME" 2>/dev/null; then
log_success "Volume ejected successfully"
else
log_warning "Normal eject failed, trying force unmount..."
if diskutil unmountDisk force "$device_id" && diskutil eject "$device_id"; then
log_success "Volume force-ejected successfully"
else
log_error "Failed to eject volume"
return 11
fi
fi
}
update_symlinks() {
if [[ $DRY_RUN -eq 1 ]]; then
log_warning "DRY RUN: Would update video symlinks"
return 0
fi
if [[ -f "$VIDEO_LINKS_SCRIPT" ]]; then
log_info "Updating video folder symlinks..."
/bin/zsh "$VIDEO_LINKS_SCRIPT" || {
log_warning "Failed to update symlinks (non-critical)"
}
else
log_debug "Video links script not found: ${VIDEO_LINKS_SCRIPT}"
fi
}
# -----------------------------------------------------------------------------
# Main Function
# -----------------------------------------------------------------------------
main() {
local start_time=$(date +%s)
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=1
shift
;;
--no-wipe)
SKIP_WIPE=1
shift
;;
--checksum)
ENABLE_CHECKSUM_VERIFY=1
shift
;;
--stats)
show_statistics
exit 0
;;
--verbose|-v)
VERBOSE=1
shift
;;
--help|-h)
show_usage
exit 0
;;
*)
log_error "Unknown option: $1"
show_usage
exit 1
;;
esac
done
print_header "📹 DJI Osmo Pocket 3 Backup & Wipe"
if [[ $DRY_RUN -eq 1 ]]; then
echo "${YELLOW}⚠️ DRY RUN MODE - No changes will be made${NC}"
echo ""
fi
echo "$(date '+%Y-%m-%d %H:%M:%S')"
echo "Host: $(hostname -s)"
echo ""
OPERATION_STARTED=1
# Check all paths
log_info "Checking paths..."
check_paths || exit 1
# Show what we're about to do
local file_count=$(count_files "$SRC_FOLDER")
local total_size=$(get_total_size "$SRC_FOLDER")
if [[ $file_count -eq 0 ]]; then
log_warning "No files found on DJI camera!"
log_info "Nothing to backup."
exit 0
fi
echo ""
log_info "Source: ${SRC_FOLDER}"
log_info "Destination: ${DEST_FOLDER}"
log_info "Files: ${file_count} (${total_size})"
if [[ $ENABLE_CHECKSUM_VERIFY -eq 1 ]]; then
log_info "Verification: Checksum (slower)"
else
log_info "Verification: Size comparison (fast)"
fi
echo ""
log_warning "This will:"
echo " 1. Copy files from DJI to ${DEST_FOLDER}"
if [[ $SKIP_WIPE -eq 1 ]]; then
echo " 2. ${YELLOW}SKIP${NC} deleting files (--no-wipe)"
echo " 3. ${YELLOW}SKIP${NC} ejecting disk (--no-wipe)"
else
echo " 2. Delete ALL FILES from ${SRC_VOLUME}"
echo " 3. Eject the disk"
fi
echo ""
# Uncomment these lines if you want confirmation
# if [[ $DRY_RUN -eq 0 ]]; then
# read "yn?Type 'yes' to confirm and proceed: "
# if [[ "$yn" != "yes" ]]; then
# log_warning "Aborting."
# exit 4
# fi
# fi
# Execute main process
copy_files
COPY_COMPLETED=1
verify_copy || {
log_error "Copy verification failed! Not wiping source."
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log_to_history "ERROR" "$file_count" "$total_size" "$duration"
send_notification "❌ DJI Backup Failed" "Verification failed - source preserved" "Basso"
exit 6
}
wipe_volume
eject_volume
update_symlinks
local end_time=$(date +%s)
local duration=$((end_time - start_time))
print_header "✅ Backup Complete"
log_success "Files saved to: ${DEST_FOLDER}"
log_success "Total files: ${file_count} (${total_size})"
log_success "Duration: ${duration}s"
echo ""
# Log to history
if [[ $DRY_RUN -eq 1 ]]; then
log_to_history "DRY_RUN" "$file_count" "$total_size" "$duration"
else
log_to_history "SUCCESS" "$file_count" "$total_size" "$duration"
fi
# Send success notification
if [[ $DRY_RUN -eq 0 ]]; then
send_notification "✅ DJI Backup Complete" "${file_count} files backed up (${total_size})" "Glass"
fi
}
# Run main function
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment