zpaq script
#!/bin/bash
Corrected paths
ARCHIVE_PATH=“/sdcard/zpaq/sixpack.05.oct.2025.zpaq” MONITOR_ROOT=“/sdcard/ccrypt” # Root directory to monitor CHECK_INTERVAL=60 LOG_FILE=“/sdcard/Download/zpaq/backup.log”
Create necessary directories
mkdir -p “\((dirname "\)ARCHIVE_PATH”)” mkdir -p “\((dirname "\)LOG_FILE”)”
Logging function
log() { echo “[$(date ‘+%Y-%m-%d %H:%M:%S’)] \(1" | tee -a "\)LOG_FILE” }
Check if zpaq is available
check_dependencies() { if ! command -v zpaq &> /dev/null; then log “ERROR: zpaq command not found. Please install zpaq in Termux.” log “Install with: pkg install zpaq” exit 1 fi }
Initialize archive with complete directory structure
initialize_archive() { log “Initializing ZPAQ archive at $ARCHIVE_PATH” log “Monitoring root: $MONITOR_ROOT”
# Change to monitor root to preserve relative paths
cd "$MONITOR_ROOT" || {
log "ERROR: Cannot change to directory $MONITOR_ROOT"
exit 1
}
# Get all files and directories in /sdcard/ccrypt/
local all_items=()
while IFS= read -r -d '' item; do
if [ -n "$item" ] && [ -e "$item" ]; then
all_items+=("$item")
fi
done < <(find . -print0 2>/dev/null)
if [ ${#all_items[@]} -gt 0 ]; then
log "Found ${#all_items[@]} items for initial backup"
# Add in batches to avoid command line length issues
local batch_size=50
for ((i=0; i<${#all_items[@]}; i+=batch_size)); do
local batch=("${all_items[@]:i:batch_size}")
if zpaq add "$ARCHIVE_PATH" "${batch[@]}" -method 4 2>> "$LOG_FILE"; then
log "Successfully added batch of ${#batch[@]} items"
else
log "ERROR: Failed to add batch of items to archive"
fi
done
log "Initial archive creation completed"
else
log "No items found for initial backup"
fi
}
Update archive with new files and directories
update_archive() { local new_items=() local temp_file temp_file=$(mktemp)
# Change to monitor root
cd "$MONITOR_ROOT" || return
# Find new or modified files and directories
if [ -f "$ARCHIVE_PATH" ]; then
# Find files modified since last backup
find . -newer "$ARCHIVE_PATH" -print0 2>/dev/null > "$temp_file"
else
# Find all files if archive doesn't exist
find . -print0 2>/dev/null > "$temp_file"
fi
# Read null-separated items into array
if [ -s "$temp_file" ]; then
while IFS= read -r -d '' item; do
if [ -n "$item" ] && [ -e "$item" ]; then
new_items+=("$item")
fi
done < "$temp_file"
fi
rm -f "$temp_file"
# Process new items
if [ ${#new_items[@]} -gt 0 ]; then
log "Found ${#new_items[@]} new/modified items"
# Log new directories specifically
for item in "${new_items[@]}"; do
if [ -d "$item" ]; then
log "New directory detected: $item"
fi
done
# Add items in batches to avoid command line length issues
local batch_size=50
for ((i=0; i<${#new_items[@]}; i+=batch_size)); do
local batch=("${new_items[@]:i:batch_size}")
if zpaq add "$ARCHIVE_PATH" "${batch[@]}" -method 4 2>> "$LOG_FILE"; then
log "Successfully added batch of ${#batch[@]} items"
else
log "ERROR: Failed to add batch of items to archive"
fi
done
# Update archive timestamp
touch "$ARCHIVE_PATH"
fi
}
Function to verify archive contents
verify_archive() { if [ -f “\(ARCHIVE_PATH" ]; then log "Verifying archive contents..." zpaq list "\)ARCHIVE_PATH” | head -20 | tee -a “\(LOG_FILE" local total_count=\)(zpaq list”$ARCHIVE_PATH” | grep -c “^-”) log “Total items in archive: $total_count” fi }
Monitor function
monitor_directories() { log “Starting recursive directory monitoring service” log “Monitoring root: $MONITOR_ROOT” log “Archive: $ARCHIVE_PATH” log “Check interval: $CHECK_INTERVAL seconds”
# Initial verification
verify_archive
while true; do
update_archive
sleep "$CHECK_INTERVAL"
done
}
Signal handling for clean shutdown
cleanup() { log “Monitoring stopped by user” exit 0 }
trap cleanup SIGINT SIGTERM
One-time backup function
one_time_backup() { check_dependencies
if [ ! -f "$ARCHIVE_PATH" ]; then
log "First run - creating initial archive"
initialize_archive
else
log "Updating existing archive with new changes"
update_archive
fi
verify_archive
}
Main execution with monitoring
main() { check_dependencies
if [ ! -f "$ARCHIVE_PATH" ]; then
log "First run - creating initial archive"
initialize_archive
else
log "Existing archive found, resuming monitoring"
fi
monitor_directories
}
Show usage
usage() { echo “Usage: $0 [option]” echo “Options:” echo ” (no option) - Start continuous monitoring” echo ” once - Run one-time backup and exit” echo ” verify - Verify archive contents and exit” echo ” help - Show this help message” }
Parse command line arguments
case “${1:-}” in “once”) one_time_backup ;; “verify”) verify_archive ;; “help”|“-h”|“–help”) usage ;; ““) main ;; *) echo “Unknown option: $1” usage exit 1 ;; esac