views:

113

answers:

2

Consider two directories:

/home/user/music/flac
/media/MUSIC/flac

I would like the second directory (destination; a USB drive) to contain the same files and structure as the first directory (master). There are 3600+ files (59G in total). Every file is scanned using unison, which is painfully slow. I would rather it compare based on file name, size, and modification time.

I think rsync might be better but the examples from the man pages are rather cryptic, and Google searches did not reveal any simple, insightful examples. I would rather not accidentally erase files in the master. ;-)

The master list will change over time: directories reorganized, new files added, and existing files updated (e.g., re-tagging). Usually the changes are minor; taking hours to complete a synchronization strikes me as sub-optimal.

What is the exact command to sync the destination directory with the master?

The command should copy new files, reorganize moved files (or delete then copy), and copy changed files (based on date). The destination files should have their timestamp set to the master's timestamp.

+2  A: 

You can use rsync this way:

rsync --delete -r -u /home/user/music/flac/* /media/MUSIC/flac

It will delete files in /media/MUSIC/flac (never on master), and update based on file date.

There are more options, but I think this way is sufficient for you. :-)

(I just did simple tests! Please test better!)

oznek
`rsync` is designed to speed these kinds of synchronisations across a network, so you don't have to send all 59G. It doesn't speed it up on a local machine, because both sender and reciever still have to read everything in their respective trees.
caf
This works. It was slow because, as it turns out, there were a number of files that had different sizes. Subsequent runs of rsync are nearly instantaneous. Thank you! I added the "-t" option to duplicate the timestamp, as well.
Dave Jarvis
A: 

You can use plain old cp to copy new & changed files (as long as your filesystems have working timestamps):

cp -dpRuv /home/user/music/flac /media/MUSIC/

To delete files from the destination that don't exist at the source, you'll need to use find. Create a script /home/user/bin/remover.sh like so:

#!/bin/bash

CANONNAME="$PWD/$(basename $1)"
RELPATH=$(echo "$CANONNAME" | sed -e "s@/media/MUSIC/flac/@@")
SOURCENAME="/home/user/music/flac/$RELPATH"

if [ ! -f "$SOURCENAME" ]; then
        echo "Removing $CANONNAME"
        rm "$CANONNAME"
fi

Make it executable, then run it from find:

find /media/MUSIC/flac -type f -execdir /home/user/bin/remover.sh "{}" \;

The only thing this won't do is remove directories from the destination that have been removed in the source - if you want that too you'll have to make a third pass, with a similar find/script combination.

caf
Thanks for this. I thought about writing a script, but really wanted to use rsync (in case I needed to transfer the files remotely).
Dave Jarvis