#!/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."