Crates.io | tracksync |
lib.rs | tracksync |
version | 0.1.1 |
source | src |
created_at | 2024-11-01 19:29:00.612522 |
updated_at | 2024-11-04 09:42:14.418764 |
description | A command-line tool to manage music library syncing to neatly ordered directories. |
homepage | |
repository | |
max_upload_size | |
id | 1432197 |
size | 175,046 |
tracksync
: if rsync
was ID3-awaretracksync
synchronizes music files from a source to a destination, keeping a database for both.
Tracks need to be added to the source database first, and then can be synced on the destination.
There is no maximum amount of destinations you can have, each one will maintain its database and can be kept in sync with the source.
The destination tree structure is ordered by artist, album, disc number, and track name, as detailed by each ID3 tag.
Pass -h
to each subcommand to understand how to use it!
tracksync
can also create hardlinks instead of copies of your files: pass the --link
flag to sync
to do so.
cargo install tracksync
You need a Rust compiler.
Once you have that setup:
git clone https://github.com/gsora/tracksync
cd tracksync
cargo build --release
./target/release/tracksync -h
You might want to exclude some tracks from the syncing process, based on various assumption.
Since this tool has been built primarily for my own consumption, I added a programmable way of defining filters.
Each destination can contain a filter written in the Rhai: you have the full
power of a regex matching function -- regex_match
-- and a Turing-complete programming language, have fun!
Filters can be created in-place or read from a file.
Each filter must define the filter(track)
function in order to be evaluated:
fn filter(track) {
// your logic goes here
true
}
As you can see, filter
returns a boolean value:
true
: copy this trackfalse
: the oppositeThe track
argument is an object that contains the following fields:
pub struct BaseTrack {
pub title: String,
pub artist: String,
pub album: String,
pub number: i64,
pub file_path: String,
pub disc_number: i64,
pub disc_total: i64,
pub extension: String,
}
As you can see, there's lots of stuff you can do with this functionality.
For example, here's a filter I built to avoid copying instrumental tracks from special edition albums:
fn filter(track) {
track.title.make_lower();
track.artist.make_lower();
let excluded_artists = [
"periphery",
"i built the sky",
"anup sastry",
"louis cole",
"vulfpeck"
];
for ea in excluded_artists {
if track.artist == ea {
return false
}
}
regex_match("instru*", track.title)
}
This is the first CLI tool I wrote in Rust, as a way of making myself familiar with the language: expect bugs.
The database schema might break suddenly, making your source and destination(s) libraries unusable: a rescan
command
is in the works -- I will make sure to keep those at a minimum.