#!/usr/bin/env bash # Sync and transcode music files to a destination directory set -e SRC="${1:?Source directory required}" DST="${2:?Destination directory required}" JOBS="${3:-12}" command -v opusenc >/dev/null || { echo "ERROR: opusenc not found" >&2; exit 1; } mkdir -p "$DST" echo "Syncing music from $SRC to $DST (using $JOBS parallel jobs)" # Process source files in parallel process_file() { local src="$1" local rel="${src#"$SRC/"}" local dst="$DST/$rel" case "${src,,}" in *.flac) dst="${dst%.*}.opus" if [[ ! -f "$dst" || "$src" -nt "$dst" ]]; then echo "Converting: $rel" mkdir -p "$(dirname "$dst")" opusenc --quiet --bitrate 160 --vbr "$src" "$dst" fi ;; *.mp3) if [[ ! -f "$dst" || "$src" -nt "$dst" ]]; then echo "Copying: $rel" mkdir -p "$(dirname "$dst")" cp -p "$src" "$dst" fi ;; esac } export -f process_file export SRC DST find -L "$SRC" -type f \( -iname "*.flac" -o -iname "*.mp3" \) -print0 | \ xargs -0 -P "$JOBS" -I {} bash -c 'process_file "$@"' _ {} # Remove stray files while IFS= read -r -d '' dst; do rel="${dst#"$DST/"}" base="${rel%.*}" case "${dst,,}" in *.opus) [[ -f "$SRC/$base.flac" || -f "$SRC/$base.FLAC" ]] && continue echo "Removing: $rel" rm -f "$dst" ;; *.mp3) [[ -f "$SRC/$rel" ]] && continue echo "Removing: $rel" rm -f "$dst" ;; esac done < <(find -L "$DST" -type f \( -iname "*.opus" -o -iname "*.mp3" \) -print0) # Clean empty directories find "$DST" -type d -empty -delete 2>/dev/null || true echo "Done"