in reply to Generate m3u files automatically

This script assumes you are running on a unixy-type system

It also assumes you are willing to edit the script every time you want to run it on some different directory (other than "/steeler/mp3", which doesn't exist on most "unixy-type" systems ;)

And it assumes that if the directory contains any mp3 file, then it contains nothing but mp3 files -- all files get listed in your "m3u" file (including the m3u file, if the script has been run previously on that path).

And it assumes that there will never be a problem with opening "m3u" files for output, or that you don't care when open fails.

There's no need to make any of these assumptions (and no need for chdir):

#!/usr/bin/perl use strict; use warnings; use File::Find::Rule; use File::Spec; die "Usage: $0 path/to/search\n" unless ( @ARGV == 1 and -d $ARGV[0] ) +; my @dirs = File::Find::Rule->directory()->in( $ARGV[0] ) or die "Can't find anything in $ARGV[0]\n"; for my $dir ( @dirs ) { my @mp3s = File::Find::Rule->maxdepth(1)->file()->name("*.[Mm][Pp] +3")->in($dir); if ( @mp3s ) { ( my $m3u = ( File::Spec->splitdir( $dir ))[-1] ) =~ s/[\s.']+ +//g; if ( open( M3U, ">", "$dir/$m3u.m3u" )) { print M3U "$_\n" for ( @mp3s ); close M3U; warn sprintf( "%d mp3s listed in %s\n", scalar @mp3s, "$di +r/$m3u.m3u" ); } else { warn "Unable to create $dir/$m3u.m3u : $!\n"; } } }
Updated second call to File::Find::Rule so that it matches *.MP3 as well as *.mp3 (and *.mP3 and *.Mp3). Also fixed syntax error (added missing quotes in sprintf arg).

Replies are listed 'Best First'.
Re^2: Generate m3u files automatically
by ikegami (Patriarch) on May 07, 2010 at 20:44 UTC

    I find it peculiar that the file system is scanned twice. The following avoids that:

    #!/usr/bin/perl use strict; use warnings; use File::Find::Rule qw( ); use Path::Class qw( file ); die "Usage: $0 path/to/search\n" if @ARGV != 1 || !-d $ARGV[0]; my @scan = File::Find::Rule ->name(qr/\.mp3\z/i) #->file ->in( $ARGV[0] ); my $last_dir = ''; my $fh; for (@scan) { my $file = file($_); my $dir = $file->dir; if ($dir ne $last_dir) { $dir = $last_dir; my $m3u = $dir->dir_list(-1); $m3u =~ s/[\s.']+//g; $m3u = $dir->file("$m3u.m3u"); open($fh, '>', $m3u) or warn("Unable to create \"$m3u\": $!\n"); } print($fh "$_\n"); }

    Untested.

    Note that this (and previous solutions) will probably create an m3u named "..m3u" if you pass "." for argument and that directory contains mp3s. This can be solved by changing
    ->in( $ARGV[0] )
    to
    ->in( dir($ARGV[0])->absolute )
    (Don't forget to import dir.)

    (Should have been a reply to the OP. The OP was notified.)