Home > OS >  Split array into groups of three instead of groups of two
Split array into groups of three instead of groups of two

Time:07-14

Currently I have this backup script working just fine in Unraid. I can add as many backup jobs to the array below as I like and the script will loop through these one after the other until all are done.

#!/bin/bash

# backup source to destination
backup_jobs=(
# source                         # destination
"/mnt/user/isos"                 "/mnt/disks/Backup"
"/mnt/user/data"               "/mnt/disks/Backup"
)

# loop through all backup jobs
for i in "${!backup_jobs[@]}"; do

    # get source path and skip to next element
    ! (( i % 2 )) && src_path="${backup_jobs[i]}" && continue

    # get destination path
    dst_path="${backup_jobs[i]}"
    
    #run backup
    rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "$src_path" "$dst_path"

Now I would like to also have a subfolder for the rsync-logs per backup job.

For that I'd like to add a name to the array for each job - but I cannot figure out how to get the loop to load that 3rd variable per line per loop like the other 2 variables. :(

backup_jobs=(
    # source                    # destination         # jobname
    "/mnt/user/isos"            "/mnt/disks/Backup"   "isos"
    "/mnt/user/data"            "/mnt/disks/Backup"   "backup"
    )

Anyone able to help? :)

CodePudding user response:

Use i % 3 instead of i % 2. This will be 0 for the source path, 1 for the destination path, and 2 for the job name.

for i in "${!backup_jobs[@]}"; do
    case $(($i % 3)) in
        0) src_path="${backup_jobs[i]}"; continue ;;
        1) dst_path="${backup_jobs[i]}"; continue ;;
        2) job_name="${backup_jobs[i]}" ;;
    esac
    
    #run backup
    rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/"$job_name"/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "$src_path" "$dst_path"
done

CodePudding user response:

#!/bin/bash

declare -A backup_jobs=(
        [source,1]="/mnt/user/isos" 
        [destination,1]="/mnt/disks/Backup"
        [jobname,1]="isos"
        [foo,1]="foo" 
        [bar,1]="bar"
        [source,2]="/mnt/user/data" 
        [destination,2]="/mnt/disks/Backup" 
        [jobname,2]="backup"
        [foo,2]="foo" 
        [bar,2]="bar"
)

LEN=$(tr ' ' '\n' <<<"${!backup_jobs[@]}"|sort -r|sed -n 's/.*,//; 1p')

for((i=1; i<=LEN; i  )); do
   echo "------- Backup $i -------"
   echo "source: ${backup_jobs[source,$i]}"
   echo "destination: ${backup_jobs[destination,$i]}"
   echo "jobname: ${backup_jobs[jobname,$i]}"
   
   #  rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/${backup_jobs[jobname,$i]}/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "${backup_jobs[source,$i]}" "${backup_jobs[destination,$i]}"
done

Output:

------- Backup 1 -------
source: /mnt/user/isos
destination: /mnt/disks/Backup
jobname: isos
------- Backup 2 -------
source: /mnt/user/data
destination: /mnt/disks/Backup
jobname: backup

CodePudding user response:

Using a function which benefit of built-in arguments stack features is certainly a more appropriate and direct approach; rather than re-implementing the arguments stack using shell arithmetic on array indexes.

With bash array:

#!/bin/bash

backup_jobs=(
  # source                    # destination         # jobname
  "/mnt/user/isos"            "/mnt/disks/Backup" "isos"
  "/mnt/user/data"            "/mnt/disks/Backup" "backup"
)

do_backup() {
  while
    src_path=$1
    dst_path=$2
    job_name=$3
    shift 3 2> /dev/null
  do #run backup
    echo rsync \
      --archive --verbose --delete \
      --log-file="/mnt/disks/Backup/rsync-logs/$job_name/log.$(date ' %Y_%m_%d__%H_%M_%S').log" \
      --progress --exclude '.Recycle.Bin' \
      "$src_path" "$dst_path"
  done
}

do_backup "${backup_jobs[@]}"

Now even an array is not necessary, and it can stick to the POSIX-shell grammar:

#!/bin/sh

do_backup() {
  while
    src_path=$1
    dst_path=$2
    job_name=$3
    shift 3 2> /dev/null
  do #run backup
    echo rsync \
      --archive --verbose --delete \
      --log-file="/mnt/disks/Backup/rsync-logs/$job_name/log.$(date ' %Y_%m_%d__%H_%M_%S').log" \
      --progress --exclude '.Recycle.Bin' \
      "$src_path" "$dst_path"
  done
}

  # source                    # destination         # jobname
do_backup \
  "/mnt/user/isos"            "/mnt/disks/Backup"  "isos" \
  "/mnt/user/data"            "/mnt/disks/Backup"  "backup"
  • Related