Monday, October 6, 2025

How to create backups of a whole directory with zpaq incremental compressed file in real time as every new file is added.

zpaq command concatenated with directory monitoring.

the script should create initially a zpaq file called file.zpaq which is incremental, has maximum compression and does the following:

it has subdirectories. each subdirectory is given new files. the script checks all subdirs and the main dir for the new files and adds the files to the subdir hierarchy within the file.zpaq directory.

hierarchy would be

file.zpaq: subdir1 subdir2 subdir3

and subdir1, 2 and 3 have respective subdirs called a,b ,c, d.

so no matter where the subdirs or dir which the script is monitoring, everytime a new file is put in there will be added to the file.zpaq with the same exact dir hierarchy.

the file.zpaq is incremental and has maximum compression option.

the file.zpaq is created in /sdcard/compressed/1/ path.

in Termux CLI.

#!/bin/bash

Configuration

ARCHIVE_PATH=“/sdcard/compressed/1/file.zpaq” MONITOR_DIRS=(“.” “subdir1” “subdir2” “subdir3”) # Add directories to monitor CHECK_INTERVAL=30 # Check for new files every 30 seconds

Create archive directory if it doesn’t exist

mkdir -p “$(dirname “$ARCHIVE_PATH”)”

Function to initialize the archive

initialize_archive() { echo “Initializing ZPAQ archive at $ARCHIVE_PATH” # Create initial archive with maximum compression zpaq add “$ARCHIVE_PATH” * -method 4 for dir in “${MONITOR_DIRS[@]}”; do if [ -d “$dir” ]; then zpaq add “$ARCHIVE_PATH” “$dir” -method 4 fi done }

Function to check for new files and update archive

update_archive() { local new_files=()

# Check main directory and all subdirectories
for dir in "\${MONITOR_DIRS[@]}"; do
    if [ -d "\$dir" ]; then
        # Find files modified in the last CHECK_INTERVAL seconds
        while IFS= read -r -d '' file; do
            if [ -n "\$file" ]; then
                new_files+=("\$file")
            fi
        done < <(find "\$dir" -type f -newer "\$ARCHIVE_PATH" -print0 2>/dev/null)
        
        # Also check for any files if archive doesn't exist yet
        if [ ! -f "\$ARCHIVE_PATH" ]; then
            while IFS= read -r -d '' file; do
                if [ -n "\$file" ]; then
                    new_files+=("\$file")
                fi
            done < <(find "\$dir" -type f -print0 2>/dev/null)
        fi
    fi
done

# Add new files to archive if any found
if [ \${#new_files[@]} -gt 0 ]; then
    echo "Found \${#new_files[@]} new/modified files. Updating archive..."
    printf '%s\n' "\${new_files[@]}"
    zpaq add "\$ARCHIVE_PATH" "\${new_files[@]}" -method 4
    echo "Archive updated successfully"
fi

}

Function to monitor continuously

monitor_directories() { echo “Starting directory monitoring…” echo “Monitoring: ${MONITOR_DIRS[*]}” echo “Archive: $ARCHIVE_PATH” echo “Check interval: $CHECK_INTERVAL seconds” echo “Press Ctrl+C to stop monitoring”

while true; do
    update_archive
    sleep "\$CHECK_INTERVAL"
done

}

Main execution

if [ ! -f “$ARCHIVE_PATH” ]; then echo “Creating initial archive…” initialize_archive fi

Start monitoring

monitor_directories

Here’s a script that monitors directories and maintains an incremental ZPAQ archive with the directory hierarchy:

#!/bin/bash

# Configuration
ARCHIVE_PATH="/sdcard/compressed/1/file.zpaq"
MONITOR_DIRS=("." "subdir1" "subdir2" "subdir3")  # Add directories to monitor
CHECK_INTERVAL=30  # Check for new files every 30 seconds

# Create archive directory if it doesn't exist
mkdir -p "\$(dirname "\$ARCHIVE_PATH")"

# Function to initialize the archive
initialize_archive() {
    echo "Initializing ZPAQ archive at \$ARCHIVE_PATH"
    # Create initial archive with maximum compression
    zpaq add "\$ARCHIVE_PATH" * -method 4
    for dir in "\${MONITOR_DIRS[@]}"; do
        if [ -d "\$dir" ]; then
            zpaq add "\$ARCHIVE_PATH" "\$dir" -method 4
        fi
    done
}

# Function to check for new files and update archive
update_archive() {
    local new_files=()
    
    # Check main directory and all subdirectories
    for dir in "\${MONITOR_DIRS[@]}"; do
        if [ -d "\$dir" ]; then
            # Find files modified in the last CHECK_INTERVAL seconds
            while IFS= read -r -d '' file; do
                if [ -n "\$file" ]; then
                    new_files+=("\$file")
                fi
            done < <(find "\$dir" -type f -newer "\$ARCHIVE_PATH" -print0 2>/dev/null)
            
            # Also check for any files if archive doesn't exist yet
            if [ ! -f "\$ARCHIVE_PATH" ]; then
                while IFS= read -r -d '' file; do
                    if [ -n "\$file" ]; then
                        new_files+=("\$file")
                    fi
                done < <(find "\$dir" -type f -print0 2>/dev/null)
            fi
        fi
    done
    
    # Add new files to archive if any found
    if [ \${#new_files[@]} -gt 0 ]; then
        echo "Found \${#new_files[@]} new/modified files. Updating archive..."
        printf '%s\n' "\${new_files[@]}"
        zpaq add "\$ARCHIVE_PATH" "\${new_files[@]}" -method 4
        echo "Archive updated successfully"
    fi
}

# Function to monitor continuously
monitor_directories() {
    echo "Starting directory monitoring..."
    echo "Monitoring: \${MONITOR_DIRS[*]}"
    echo "Archive: \$ARCHIVE_PATH"
    echo "Check interval: \$CHECK_INTERVAL seconds"
    echo "Press Ctrl+C to stop monitoring"
    
    while true; do
        update_archive
        sleep "\$CHECK_INTERVAL"
    done
}

# Main execution
if [ ! -f "\$ARCHIVE_PATH" ]; then
    echo "Creating initial archive..."
    initialize_archive
fi

# Start monitoring
monitor_directories

Here’s also a more advanced version with better error handling and logging:

#!/bin/bash

# Enhanced version with logging and error handling
ARCHIVE_PATH="/sdcard/compressed/1/file.zpaq"
MONITOR_DIRS=("." "subdir1" "subdir2" "subdir3" "subdir1/a" "subdir1/b" "subdir2/c" "subdir2/d" "subdir3/a" "subdir3/b")
CHECK_INTERVAL=60
LOG_FILE="/sdcard/compressed/1/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
initialize_archive() {
    log "Initializing ZPAQ archive at \$ARCHIVE_PATH"
    
    local first_run=true
    for dir in "\${MONITOR_DIRS[@]}"; do
        if [ -d "\$dir" ] && [ "\$(ls -A "\$dir" 2>/dev/null)" ]; then
            if [ "\$first_run" = true ]; then
                zpaq add "\$ARCHIVE_PATH" "\$dir" -method 4 2>> "\$LOG_FILE"
                first_run=false
            else
                zpaq add "\$ARCHIVE_PATH" "\$dir" -method 4 2>> "\$LOG_FILE"
            fi
            log "Added directory: \$dir"
        fi
    done
    
    if [ "\$first_run" = true ]; then
        log "No directories with content found for initial backup"
    else
        log "Initial archive creation completed"
    fi
}

# Update archive with new files
update_archive() {
    local new_files=()
    local temp_file
    temp_file=\$(mktemp)
    
    # Use find to locate new files
    for dir in "\${MONITOR_DIRS[@]}"; do
        if [ -d "\$dir" ]; then
            if [ -f "\$ARCHIVE_PATH" ]; then
                find "\$dir" -type f -newer "\$ARCHIVE_PATH" -print0 2>/dev/null >> "\$temp_file"
            else
                find "\$dir" -type f -print0 2>/dev/null >> "\$temp_file"
            fi
        fi
    done
    
    # Read null-separated files into array
    if [ -s "\$temp_file" ]; then
        while IFS= read -r -d '' file; do
            if [ -f "\$file" ]; then
                new_files+=("\$file")
            fi
        done < "\$temp_file"
    fi
    
    rm -f "\$temp_file"
    
    # Process new files
    if [ \${#new_files[@]} -gt 0 ]; then
        log "Found \${#new_files[@]} new/modified files"
        
        # Add files in batches to avoid command line length issues
        local batch_size=50
        for ((i=0; i<\${#new_files[@]}; i+=batch_size)); do
            local batch=("\${new_files[@]:i:batch_size}")
            if zpaq add "\$ARCHIVE_PATH" "\${batch[@]}" -method 4 2>> "\$LOG_FILE"; then
                log "Successfully added batch of \${#batch[@]} files"
            else
                log "ERROR: Failed to add batch of files to archive"
            fi
        done
        
        # Update archive timestamp
        touch "\$ARCHIVE_PATH"
    fi
}

# Monitor function
monitor_directories() {
    log "Starting directory monitoring service"
    log "Monitoring directories: \${MONITOR_DIRS[*]}"
    log "Check interval: \$CHECK_INTERVAL seconds"
    
    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

# Main execution
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
}

# Run main function
main

Setup Instructions:

  1. Install ZPAQ in Termux:
    pkg update
    pkg install zpaq
    
  2. Create the script:
    nano ~/zpaq_monitor.sh
    

    Copy and paste the script content, then save with Ctrl+X, Y, Enter

  3. Make it executable:
    chmod +x ~/zpaq_monitor.sh
    
  4. Run the script:
    cd /path/to/your/directories
    ~/zpaq_monitor.sh
    

Features:

· Incremental backups - Only adds new or modified files · Maximum compression (-method 4) · Preserves directory hierarchy in the archive · Configurable monitoring intervals · Logging with timestamps · Error handling · Batch processing to handle large numbers of files

Customization:

· Modify MONITOR_DIRS array to add your specific directories · Adjust CHECK_INTERVAL for more/less frequent checks · Change ARCHIVE_PATH for different storage location

The script will maintain the exact directory structure within the ZPAQ archive, so when you extract it, you’ll get the same hierarchy as your source directories.

No comments:

Post a Comment

Supercollider GNU FREE AND OPEN SOURCE CLI SOFTWARE AS SUPER AUDIO AND MUSIC CREATION SYSTEM VERSUS ORDINARY AUDIO SOFTWARE.

Three Most Complex Operations in SuperCollider Real-Time Polyphonic Physical Modeling Synthesis with Neural Network Control Co...