Re: Recursive scanner perl script
Dan Sully <[email protected]>
| Newsgroups | gmane.comp.audio.netjuke.user |
|---|---|
| Message-ID | <[email protected]> |
* Michael Strong <[email protected]> shaped the electrons to say... > I was just wondering if anyone had come up with a perl script that would > be able to do the job of the recursive file finder, but on the command > line. I have just installed Netjuke and I have about 2000 tracks to > import, and they are in directories based on artist, so there are about > 250 subdirs. It is excruciatingly slow to do this from the webpage, > somewhere aroung 5 tracks per minute! I wrote one a while ago and posted it to the list. It's attached. -D -- There once was a chicken named Phil. His flying saucer for breakfast rolled down a hill. The hill was made of soap. It was sort of a soap slope. On a rope. Homogenized, even.
pusher-robot
(text/plain, 5.6 KB)
#!/usr/bin/perl -w # $Id: pusher-robot,v 1.7 2002/10/07 20:24:43 daniel Exp $ # move mp3's into the correct directories. # import them into netjuke # [email protected] use strict; use DBI; use File::Basename; use File::Copy; use File::Find; use File::Path; use MP3::Info; use MP3::Tag; use POSIX qw(strftime); use URI::Escape; my $DEBUG = 1; my $INCOMING = '/bits/incoming'; my $HOME = '/bits/mp3'; my $dupeCheck = 1; my %dbiSettings = ( PrintError => 1, RaiseError => 0, ); my $dbName = 'netjuke'; my $dbUser = 'netjuke'; my $dbPass = 'insecure'; my $dbDriver = 'mysql'; my %trackCache = (); my %idCache = (); my %escapeCache = (); sub main { MP3::Info::use_winamp_genres(); my $dbh = DBI->connect("dbi:$dbDriver:$dbName", $dbUser, $dbPass, \%dbiSettings) or die $!; my ($dir,$count) = ($INCOMING,0); # parse the commandline if given while (my $arg = shift @ARGV) { if ($arg =~ /^-d/o) { $dir = shift @ARGV; next } if ($arg =~ /^-nodupe?/o) { $dupeCheck = 0; shift @ARGV; next } } # find files to import find sub { my $file = $File::Find::name; return unless $file =~ /\.mp3$/io; return unless -f $file; my ($artist,$album) = process($dbh,$file); # don't move the file if we didn't import it. return unless defined $artist and defined $album; my $destDir = "$HOME/$artist/$album"; my $destFile = "$destDir/" . basename($file); # only move if the dest and source are different if ($file ne $destFile) { mkpath([$destDir], 0, 0775) unless -d $destDir; move($file, $destDir) or warn "Can't move [$file] to [$destDir]: $!"; } }, $dir; # update the counts while (my ($table,$data) = each %trackCache) { while (my ($id,$value) = each %$data) { updateCount($dbh,$table,'increment',$value,$id); } } } # get the artist/album/genre id if it exists. otherwise increment. sub findId { my ($dbh,$table,$name) = @_; my $cnt = 0; my $err = ''; my $id = 1; if (!defined $name or length($name) == 0) { return wantarray ? ($id,$cnt,$err) : $id; } if (defined $idCache{$table}->{$name}) { return $idCache{$table}->{$name}; } my $select = $dbh->prepare_cached("SELECT id FROM $table WHERE name = ?"); if ($select->execute($name) && $select->rows() < 1) { my $insert = $dbh->prepare_cached("INSERT INTO $table (name) VALUES (?)"); if ($insert->execute($name)) { $select->finish(); $select->execute(); } } $id = $idCache{$table}->{$name} = ($select->fetchrow_array())[0]; $select->finish(); $cnt++; return wantarray ? ($id,$cnt,$err) : $id; } sub updateCount { my ($dbh,$table,$action,$val,$id) = @_; if ($action eq 'increment') { $dbh->do("update $table set track_cnt = track_cnt + $val where id = $id"); } elsif ($action eq 'decrement') { $dbh->do("update $table set track_cnt = track_cnt - $val where id = $id"); } else { $dbh->do("update $table set track_cnt = 0 where track_cnt < 1 or track_cnt is null"); } return 1; } sub process { my ($dbh,$file) = @_; my $tag = get_mp3tag($file); my $info = get_mp3info($file); # try and get data from the filename if (scalar keys %$tag != 4) { my %auto = (); my $mp3 = MP3::Tag->new($file); $mp3->config('autoinfo','filename'); ($auto{'TITLE'}, $auto{'TRACKNUM'}, $auto{'ARTIST'}, $auto{'ALBUM'}) = $mp3->autoinfo(); # try and get data from the filename for my $field (qw(TITLE TRACKNUM ARTIST ALBUM)) { next if defined $tag->{$field} and $tag->{$field} !~ /^\s*$/; if (defined $auto{$field} and $auto{$field} !~ /^\s*$/) { $tag->{$field} = $auto{$field}; } } } my ($song, $track, $artist, $album) = ($tag->{'TITLE'},$tag->{'TRACKNUM'} || 1,$tag->{'ARTIST'},$tag->{'ALBUM'}); # normalize if ($track =~ m|^(\d+)/\d+$|) { $track = $1; } if (defined $artist and $artist !~ /^\s*$/) { $artist =~ s/^Various Artists$/Various/i; } else { print "artist is undefined for file: [$file]\n"; return; } printf("Working on: %32s %64s\n", $artist,$song) if $DEBUG; my $date = strftime("%Y-%m-%d %H:%M:%S", localtime((stat($file))[9])); # escape the file. cache results. $file = join('/', ( $escapeCache{$artist} ||= uri_escape($artist), $escapeCache{$album} ||= uri_escape($album), uri_escape(basename($file))) ); my %data = ( 'name' => $song, 'size' => $info->{'SIZE'} || (stat(_))[7], 'time' => $info->{'TIME'}, 'track_number' => $track, 'kind' => 'MPEG AUDIO FILE', 'date' => "'$date'", 'bit_rate' => $info->{'BITRATE'}, 'sample_rate' => int($info->{'FREQUENCY'} * 1000), 'location' => $file, ); # check for a duplicate entry if ($dupeCheck) { my $dupe = $dbh->prepare_cached("select id from netjuke_tracks where location = ?"); if ($dupe->execute($file) && $dupe->rows() > 1) { print "duplicate! skipping $artist - $song\n"; $dupe->finish(); return undef; } $dupe->finish(); } # Get Artist, Album & Genre ID based on their respective names. $data{'ar_id'} = findId($dbh,'netjuke_artists', $artist); $data{'al_id'} = findId($dbh,'netjuke_albums', $album); $data{'ge_id'} = findId($dbh,'netjuke_genres', $tag->{'GENRE'}); my (@columns, @values) = (); while (my ($key, $value) = each %data) { push @columns, $key; push @values, $value; } my $insert = $dbh->prepare_cached('INSERT INTO netjuke_tracks ('. join(',',@columns).') VALUES ('. join(',', (map { '?' } @values)) .')'); unless ($insert->execute(@values)) { print "An error occured on insert. Skipping $file\n"; return; } else { $insert->finish(); $trackCache{'netjuke_artists'}->{$data{'ar_id'}}++; $trackCache{'netjuke_albums'}->{$data{'al_id'}}++; $trackCache{'netjuke_genres'}->{$data{'ge_id'}}++; } return ($artist,$album); } main(); __END__