Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/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."
Advertisement