CCCPaste

fat32_copy..sh

#!/usr/bin/env bash
set -uo pipefail

# Define paths dynamically using the current user
# Quoting handles potential spaces in the username safely
current_user="$(whoami)"
src="/home/$current_user/Music/RythmBox"
dst="/media/$current_user/MUSIC"

max_component=255

sanitize_comp() {
  local comp="$1"
  
  # 1. Transliterate to ASCII. If iconv fails, fallback to original.
  local trans
  trans=$(printf '%s' "$comp" | iconv -f UTF-8 -t ASCII//TRANSLIT 2>/dev/null) || trans="$comp"
  comp="$trans"

  # 2. Clean characters: remove control chars, swap spaces for _, swap forbidden for -
  comp=$(printf '%s' "$comp" | \
    tr -d '[:cntrl:]' | \
    sed -E 's/[[:space:]]+/_/g; s/[<>:"\/\\|?*]+/-/g')

  # 3. Trim leading/trailing dots and spaces (FAT32 dislikes these)
  comp=$(printf '%s' "$comp" | sed -E 's/^[ .]+//; s/[ .]+$//')

  # 4. Handle empty result
  if [ -z "$comp" ]; then comp="_"; fi

  # 5. Byte-limit truncation using Perl (preserves multibyte boundaries)
  comp=$(printf '%s' "$comp" | perl -CS -pe 'use bytes; $_ = substr($_,0,'$max_component');')
  
  printf '%s' "$comp"
}

echo "Starting copy..."
echo "Source: $src"
echo "Dest:   $dst"

# Process files
find "$src" -print0 | while IFS= read -r -d '' path; do
  
  # Calculate relative path
  rel=${path#"$src"/}
  if [ "$path" = "$src" ]; then rel=""; fi

  # Reconstruct the path with sanitized components
  IFS='/' read -r -a comps <<< "$rel"
  safe_path=""
  for comp in "${comps[@]}"; do
    [ -z "$comp" ] && continue
    safe_comp=$(sanitize_comp "$comp")
    safe_path="$safe_path/$safe_comp"
  done
  # Remove leading slash from reconstruction
  safe_path=${safe_path#/}

  # Define full source and destination paths
  src_full="$path"
  dst_full="$dst/$safe_path"

  if [ -d "$src_full" ]; then
    # It's a directory
    if [ ! -d "$dst_full" ]; then
        mkdir -p "$dst_full"
    fi
  elif [ -f "$src_full" ]; then
    # It's a file
    mkdir -p "$(dirname "$dst_full")"

    # Only copy if destination doesn't exist OR source is newer
    if [ ! -e "$dst_full" ] || [ "$src_full" -nt "$dst_full" ]; then
        cp -p -- "$src_full" "$dst_full" || echo "Error copying: $src_full"
    fi
  fi
done

echo "Operation complete."