jpenguin

fat32_copy..sh

Dec 26th, 2025
4,150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 2.24 KB | None | 0 0
  1. #!/usr/bin/env bash
  2. set -uo pipefail
  3.  
  4. # Define paths dynamically using the current user
  5. # Quoting handles potential spaces in the username safely
  6. current_user="$(whoami)"
  7. src="/home/$current_user/Music/RythmBox"
  8. dst="/media/$current_user/MUSIC"
  9.  
  10. max_component=255
  11.  
  12. sanitize_comp() {
  13.   local comp="$1"
  14.  
  15.   # 1. Transliterate to ASCII. If iconv fails, fallback to original.
  16.   local trans
  17.   trans=$(printf '%s' "$comp" | iconv -f UTF-8 -t ASCII//TRANSLIT 2>/dev/null) || trans="$comp"
  18.   comp="$trans"
  19.  
  20.   # 2. Clean characters: remove control chars, swap spaces for _, swap forbidden for -
  21.   comp=$(printf '%s' "$comp" | \
  22.     tr -d '[:cntrl:]' | \
  23.     sed -E 's/[[:space:]]+/_/g; s/[<>:"\/\\|?*]+/-/g')
  24.  
  25.   # 3. Trim leading/trailing dots and spaces (FAT32 dislikes these)
  26.   comp=$(printf '%s' "$comp" | sed -E 's/^[ .]+//; s/[ .]+$//')
  27.  
  28.   # 4. Handle empty result
  29.   if [ -z "$comp" ]; then comp="_"; fi
  30.  
  31.   # 5. Byte-limit truncation using Perl (preserves multibyte boundaries)
  32.   comp=$(printf '%s' "$comp" | perl -CS -pe 'use bytes; $_ = substr($_,0,'$max_component');')
  33.  
  34.   printf '%s' "$comp"
  35. }
  36.  
  37. echo "Starting copy..."
  38. echo "Source: $src"
  39. echo "Dest:   $dst"
  40.  
  41. # Process files
  42. find "$src" -print0 | while IFS= read -r -d '' path; do
  43.  
  44.   # Calculate relative path
  45.   rel=${path#"$src"/}
  46.   if [ "$path" = "$src" ]; then rel=""; fi
  47.  
  48.   # Reconstruct the path with sanitized components
  49.   IFS='/' read -r -a comps <<< "$rel"
  50.   safe_path=""
  51.   for comp in "${comps[@]}"; do
  52.     [ -z "$comp" ] && continue
  53.     safe_comp=$(sanitize_comp "$comp")
  54.     safe_path="$safe_path/$safe_comp"
  55.   done
  56.   # Remove leading slash from reconstruction
  57.   safe_path=${safe_path#/}
  58.  
  59.   # Define full source and destination paths
  60.   src_full="$path"
  61.   dst_full="$dst/$safe_path"
  62.  
  63.   if [ -d "$src_full" ]; then
  64.     # It's a directory
  65.     if [ ! -d "$dst_full" ]; then
  66.         mkdir -p "$dst_full"
  67.     fi
  68.   elif [ -f "$src_full" ]; then
  69.     # It's a file
  70.     mkdir -p "$(dirname "$dst_full")"
  71.  
  72.     # Only copy if destination doesn't exist OR source is newer
  73.     if [ ! -e "$dst_full" ] || [ "$src_full" -nt "$dst_full" ]; then
  74.         cp -p -- "$src_full" "$dst_full" || echo "Error copying: $src_full"
  75.     fi
  76.   fi
  77. done
  78.  
  79. echo "Operation complete."
Advertisement