I use a set of Perl scripts to manage my music library in Linux. For each of my digital audio players (DAP), I have a local copy on my PC of their ‘music’ directory. This local copy contains hard links to the music files in my PC’s main music repository (which avoids duplicating the files for each device). I then use rsync to synchronise each DAP with its local copy on the PC.

The scripts I used for my entire music management process are on Github at https://github.com/gslewis/mlencode. They comprise:


Rips and normalises my CDs. Can rip, merge and normalize multi-disc sets into one group of WAVs.


Encodes WAVs to Ogg, Flac or MP3.


Copies an album from the main music repository to a DAP’s local repository using hard links.


Synchronises a DAP with its local repository (or vice versa).

I prefer to mount my DAPs manually, rather than rely on the auto-detect/mount feature of my desktop environment (Xfce). I mount with the sync option so that the file transfer happens synchronously — I found I was getting incomplete transfers with the default async option. I also found that Xfce would mount USB devices with utf8=1 while my file names are encoded as iso-8859-1. Finally, I prefer a conventional mount point in /mnt over a ‘user friendly’ name in /run/media.

Use udevadmin to identify a fixed device name suitable for the device’s entry in /etc/fstab. There will be device names for disk/by-id, disk/by-label and disk/by-path.

Identifying a /dev entry for a DAP
/sbin/udevadm info --query=symlink --path=/sys/block/sdc

# Output contains: disk/by-label/COWON\x20J3

This means I can refer to my Cowon J3 in /etc/fstab as /dev/disk/by-label/COWON\x20J3 and set the mount options that I prefer. The /etc/fstab entries for my DAPs look like:

DAP /etc/fstab entries
# Cowon J3
/dev/disk/by-label/COWON\x20J3  /mnt/devices/J3 auto  rw,noauto,user,sync 0 0

# Cowon iAudio 9
/dev/disk/by-label/iAUDIO\x209  /mnt/devices/I9 auto  rw,noauto,user,sync 0 0

# Cowon iAudio X5L
/dev/disk/by-label/IAUDIO  /mnt/devices/X5 auto  rw,noauto,user,sync 0 0


I use rsync to synchronise each DAP with its local repository. The options to use are:


Because I want to see what is being transferred.


Recurse into sub-directories. I just specify to local and remote top-level directories.


I don’t trust modification dates on the VFAT file systems on the DAPs so I use these options to detect changed files.


When I delete a file (hard link) in the local repository, I want the file removed from the DAP.

If the local and DAP file systems use different encodings, you can use the --iconv=LOCAL,REMOTE option to change filenames during the transfer. For instance, if the local files use iso-8859-1 and the DAP uses UTF-8, add the option --iconv=iso88591,utf8.

Putting it all together, my local repository for the Cowon J3 is at /home/gsl/media/devices/J3 and I mount the J3 at /mnt/devices/J3 which means its music directory is at /mnt/devices/J3/Music. The rsync command to run is:

Synchronise local repository to DAP
rsync --verbose --recursive --update --size-only --delete \
    /home/gsl/media/devices/J3/ \

If for some reason I wanted to do the reverse and copy the contents of a DAP to a local repository, I can switch the source and destination directories. However, this is a bad move when the local repository is maintained using hard links to a main media repository as rsync will clobber any hard links, replacing them with actual files.