I therefore have to transfer the music files piece meal. I have therefore written a bit of perl that supports the copying of files but maintains a Tag file of what files have been transferred - ie its a simple mirror program that:
- Keeps a record of files that already been copied;
- Restricts the files transferred to those with a given suffix (currently .mp3);
- Fails carefully when out of space on target directory;
- Will recopy files that have changed since original copy.
Usage is (mount/umount will probably have be done as root):
- Mount memory card on your linux computer
Eg: if you're card is /dev/sdb and you have created a directory /tmp/ext, as root:
mount -t auto /dev/sdb /tmp/ext - Make sure memory card is empty:
rm -rf /tmp/ext/* - Run perl copy script calling out:
- The tags file you want to use
- The Source directory
- The Target directory on your memory card:
Eg:
./cpto.pl ~/carmusic.tags /home/music /tmp/ext/music - This will either complete fully or will fail with "No space left on device"
- Unmount the card on your linux computer:
umount /tmp/ext - Put memory card in your ICE and copy to Hard Disk selecting Replace files
- If step 4 failed with "No space left on device" then repeat from step 1.
/home/music/la_roux/la_roux/armour_love.mp3^1251554384^C /home/music/la_roux/la_roux/reflections_are_protection.mp3^1251554386^C /home/music/la_roux/la_roux/growing_pains.mp3^1251554686^C /home/music/Green Day/International Superhits/Basket Case.mp3^1235913966^C /home/music/Green Day/International Superhits/Brainstew.mp3^1235914182^C /home/music/Green Day/International Superhits/Geek Stink Breath.mp3^1235914132^C /home/music/Green Day/International Superhits/Good Riddance Time of Your Life.mp3^1235914370^C /home/music/Green Day/International Superhits/Hitchin A Ride.mp3^1235914324^C /home/music/Green Day/International Superhits/JAR Jason Andrew Relva.mp3^1235914098^C /home/music/Green Day/International Superhits/Jaded.mp3^1235914206^.Note that the file format is:
FromFileName^ModificationTime^Status
Where Status is "." if copy is in progress and "C" is completed copy. Source: cpto.pl
#!/opt/bin/perl # This perl script is used to mirro files from one dir to another # It keeps a tag file of files that have been copied and the modification time # of the source file when copy was done so that copies # are not repeated. # # It is designed to fill up a device with files to be copied until its out of space # You can then do what you want with the files on the device (eg copy them to another device) # clear the device nd run the copy again. The tags file ensures that only as yet uncopied # files are placed on the device. # # I wrote this so that I can transfer my music files to my car's enterntainment system using # a 2Gb memory card - the maximum card size supported by the ICE. # # Usage: # cpto.pl tagFileName /home/music /mnt/extcard/music # Author: Tony.Jewell@Cregganna.Com # See: http://www.tonyjewell.com/2013/10/copying-music-to-in-car-entertainment.html # Disclaimer: I take not responsibility for any damage or other nepharious effects this # script will have on your PC - use at yoru own risk. use strict; use warnings; use diagnostics; use File::stat; use File::Basename; use File::Path; if ( $#ARGV < 2 ) { print "Usage: cpto TagFile Source Destination\n"; exit 1; } my @suffixes = ( ".mp3" ); my $buffSize = 8 * 2**10; my $tagsFile = "${ARGV[0]}"; # tags is keyed by file name and value is date/time of cp from file my %tags; sub loadTags { # Check that we can write to it open (TAGS, ">>${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!"; close(TAGS); if ( -f "${tagsFile}" ) { open( my $TAGS, "<${tagsFile}") || die "Unable to open ${tagsFile}: $!"; while (my $tagLine = <$TAGS>) { chomp $tagLine; my @tag = split('\^', $tagLine); if ($#tag >= 2 && $tag[2] =~ "C") { $tags{$tag[0]} = $tag[1]; } } close(TAGS); } } # We write a start Copy to make sure there is room to write to the tags file # This writes a pending line with status "." sub tagStartCopy { my $name = shift; my $mtime = shift; open (TAGS, "+<${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!"; # Seek to end sysseek(TAGS, 0, 2 ) || die "Unable to seek file $tagsFile: $!"; my $tagPos = tell(TAGS); syswrite(TAGS, "$name^$mtime^.\n"); # Mark as pending close(TAGS) || die "Unable to close $tagsFile after writing: $!"; return $tagPos; } # Rewrite the tag line with the completed copy status of "C". sub tagEndCopy { my $tagPos = shift; my $name = shift; my $mtime = shift; open (TAGS, "+<${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!"; sysseek(TAGS, $tagPos, 0 ) || die "Unable to seek file $tagsFile: $!"; syswrite(TAGS, "$name^$mtime^C\n"); close(TAGS) || die "Unable to close $tagsFile after writing: $!"; $tags{$name} = $mtime; } sub chkDirExists { my $dir = dirname(shift); if (! -d $dir) { mkpath($dir) || die "Unable to create Directory: $dir: $!"; } } sub cpFile { my $fromName = shift; my $toName = shift; my($filename, $directories, $suffix) = fileparse($fromName, @suffixes); if ( ! $suffix ) { return; } my $from = stat($fromName) || die "Unable to stat $fromName: $!"; my $tag = $tags{$fromName}; if ( $tag && $tag >= $from->mtime ) { # Already done this one return; } print "$fromName => $toName...."; &chkDirExists($toName); my $tagPos = &tagStartCopy($fromName, $from->mtime); open( IN, "< $fromName") || die "Unable to open for Reading: $fromName: $!"; open( OUT, "> $toName") || die "Unable to open for Writing: $toName: $!"; binmode(IN); binmode(OUT); my $buff; while (read(IN, $buff, $buffSize)) { print OUT $buff; } close( IN ) || die "Unable to close for Reading: $fromName: $!"; close( OUT ) || die "Unable to close for Writing: $toName: $!"; &tagEndCopy($tagPos, $fromName, $from->mtime); print "\n"; } sub cpDir { my $fromName = shift; my $toName = shift; opendir(my $DIR, $fromName) || die "Unable to read directory: $fromName: $!"; while(my $file = readdir $DIR) { if ( ! ($file =~ /^[.]+$/ ) ) { &cp($fromName . '/' . $file, $toName . '/' . $file); } } closedir $DIR; } sub cp { my $fromName = shift; my $toName = shift; if (-d $fromName) { &cpDir($fromName, $toName); } elsif (-f $fromName) { &cpFile($fromName, $toName); } } &loadTags(); &cp($ARGV[1], $ARGV[2]);