#!/usr/bin/env bash FILE=$1 # Sparse sequence read -r -a SPARSE_ARRAY <<< "$( INDEX=0 FILE_ID=0 while read -r CHAR do if [[ $(( INDEX % 2 )) -eq 0 ]] then for (( i=1; i<=CHAR; i++ )) do printf "%s " "$FILE_ID" done (( FILE_ID++ )) else for (( i=1; i<=CHAR; i++ )) do printf "%s " '-1' done fi (( INDEX++ )) done <<< "$( sed -E 's/(.)/\1\n/g' "$FILE" | grep -v '^$' )" )" #printf "%s" "${SPARSE_ARRAY[@]}" | fold -w 100 #printf "\n" printf "Sparse array len: %s\n" "${#SPARSE_ARRAY[@]}" SHADOW_ARRAY=( "${SPARSE_ARRAY[@]}" ) # Start by working backwards j=$(( ${#SPARSE_ARRAY[@]} - 1 )) # Moveable index since file blocks jump k=0 # SHADOW_ARRAY cursor LAST_SKIP=9999 while [[ $j -ge 0 ]] do # Find a file if [[ ${SPARSE_ARRAY[j]} -eq -1 ]] then # Not a file (( j-- )) continue fi # Get file size # j moved to index before file head FILE_SIZE=0 ID=${SPARSE_ARRAY[j]} while [[ ${SPARSE_ARRAY[j]} == "$ID" ]] do (( FILE_SIZE++ )) (( j-- )) done #printf "File ID: %s, File size: %s\n" "$ID" "$FILE_SIZE" 2>&1 # Since search space is constantly decreasing # Contiguous space can only keep getting smaller if [[ $FILE_SIZE -ge $LAST_SKIP ]] then printf "File %s size %s skipped. Last skip: %s\n" "$ID" "$FILE_SIZE" "$LAST_SKIP" continue fi # Search for available contiguous space # Search from start until the file itself k=0 while [[ $k -le $j ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] do CONT_SPACE=0 # Skip ahead until first match of space while [[ ${SHADOW_ARRAY[k]} -ne -1 ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] do (( k++ )) done # Space found, now get contiguous length while [[ ${SHADOW_ARRAY[k]} -eq -1 ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] do (( CONT_SPACE++ )) (( k++ )) done # Space length is ok, can proceed if [[ $FILE_SIZE -le $CONT_SPACE ]] ;then break; fi done # Space length ok, can proceed if [[ $FILE_SIZE -le $CONT_SPACE ]] then # Move cursor to head of contiguous space (( k-= CONT_SPACE )) while [[ $FILE_SIZE -gt 0 ]] && \ [[ ${SHADOW_ARRAY[k]} -eq -1 ]] && \ [[ ${SHADOW_ARRAY[j+FILE_SIZE]} -ne -1 ]] do # Perform copy SHADOW_ARRAY[k]=$ID SHADOW_ARRAY[j+FILE_SIZE]=-1 (( k++ )) (( FILE_SIZE-- )) done else LAST_SKIP=$FILE_SIZE printf "File %s skipped. File size: %s\n" "$ID" "$FILE_SIZE" continue fi done #printf "%s " "${SHADOW_ARRAY[@]}" | fold -w 100 | tee final-result | cat printf "%s " "${SHADOW_ARRAY[@]}" > final-result #printf "\n" # Generate checksum for shadow array CHECKSUM=0 for (( i=0; i<${#SHADOW_ARRAY[@]}; i++ )) do if [[ ${SHADOW_ARRAY[i]} -ne -1 ]] ;then (( CHECKSUM += i * SHADOW_ARRAY[i] )); fi done printf "%s\n" "$CHECKSUM"