Created
November 23, 2024 19:50
-
-
Save KeironO/7d05bf5de7701662bad8b3437cd9fb56 to your computer and use it in GitHub Desktop.
sync-mp3.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Ensure dependencies are installed | |
if ! command -v rsync &> /dev/null; then | |
echo "rsync is required but not installed. Please install it with 'sudo apt install rsync'." | |
exit 1 | |
fi | |
if ! command -v sqlite3 &> /dev/null; then | |
echo "sqlite3 is required but not installed. Please install it with 'sudo apt install sqlite3'." | |
exit 1 | |
fi | |
# Prompt for the destination directory | |
read -rp "Enter the mount point of the MP3 player (destination directory): " mp3_mount | |
if [ ! -d "$mp3_mount" ]; then | |
echo "Directory $mp3_mount does not exist. Please provide a valid directory." | |
exit 1 | |
fi | |
# Define source and destination directories | |
src_dir="$HOME/media/music" | |
dest_dir="$mp3_mount/" | |
db_file="$mp3_mount/.sync_metadata.db" # SQLite database file | |
# Create SQLite database and table if not exists | |
sqlite3 "$db_file" <<EOF | |
CREATE TABLE IF NOT EXISTS file_metadata ( | |
relative_path TEXT UNIQUE, | |
size INTEGER, | |
last_modified INTEGER | |
); | |
EOF | |
# Function to get file size | |
get_file_size() { | |
local file_path="$1" | |
stat --format='%s' "$file_path" | |
} | |
# Function to get the last modification time of a file | |
get_file_mtime() { | |
local file_path="$1" | |
stat --format='%Y' "$file_path" | |
} | |
# Function to escape single quotes for SQLite | |
escape_sql() { | |
echo "$1" | sed "s/'/''/g" | |
} | |
# Sync function | |
sync_music() { | |
echo "Starting sync from $src_dir to $dest_dir..." | |
# Step 1: Create a list of all files in the source directory | |
temp_source_file_list=$(mktemp) | |
find "$src_dir" -type f > "$temp_source_file_list" | |
# Step 2: Iterate through the source files | |
total_files=$(wc -l < "$temp_source_file_list") | |
copied_files=0 | |
while IFS= read -r source_file; do | |
relative_path="${source_file#$src_dir/}" | |
dest_file="$dest_dir$relative_path" | |
mkdir -p "$(dirname "$dest_file")" | |
# Get file metadata | |
file_size=$(get_file_size "$source_file") | |
file_mtime=$(get_file_mtime "$source_file") | |
escaped_relative_path=$(escape_sql "$relative_path") | |
# Check database for existing metadata | |
db_entry=$(sqlite3 "$db_file" "SELECT size, last_modified FROM file_metadata WHERE relative_path = '$escaped_relative_path';") | |
if [ -n "$db_entry" ]; then | |
db_size=$(echo "$db_entry" | awk -F'|' '{print $1}') | |
db_mtime=$(echo "$db_entry" | awk -F'|' '{print $2}') | |
else | |
db_size="" | |
db_mtime="" | |
fi | |
# Sync file if size or modification time has changed | |
if [ "$file_size" != "$db_size" ] || [ "$file_mtime" != "$db_mtime" ]; then | |
rsync -a "$source_file" "$dest_file" | |
sqlite3 "$db_file" <<EOF | |
INSERT OR REPLACE INTO file_metadata (relative_path, size, last_modified) | |
VALUES ('$escaped_relative_path', $file_size, $file_mtime); | |
EOF | |
echo "Transferred: $relative_path | Size: $(du -h "$source_file" | cut -f1) | Status: UPDATED" | |
((copied_files++)) | |
else | |
echo "Skipped: $relative_path | Size: $(du -h "$source_file" | cut -f1) | Status: UP-TO-DATE" | |
fi | |
done < "$temp_source_file_list" | |
echo "Cleaning up removed files..." | |
sqlite3 "$db_file" "SELECT relative_path FROM file_metadata;" | while IFS= read -r relative_path; do | |
dest_file="$dest_dir$relative_path" | |
if [ ! -f "$dest_file" ]; then | |
escaped_relative_path=$(escape_sql "$relative_path") | |
echo "Removed stale file record: $relative_path | Status: DELETED" | |
sqlite3 "$db_file" "DELETE FROM file_metadata WHERE relative_path = '$escaped_relative_path';" | |
fi | |
done | |
rm "$temp_source_file_list" | |
echo "Sync complete! $copied_files files updated." | |
} | |
# Start syncing | |
sync_music |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment