View previous topic :: View next topic |
Author |
Message |
mistersnorfles n00b
Joined: 03 Aug 2007 Posts: 32
|
Posted: Sun Aug 19, 2007 12:32 pm Post subject: Script To Rename && Convert Music Files |
|
|
I am just starting to learn Perl and I am trying to write a script that will go through all of my music files and do the following:
1) Change all spaces in file names into underscores.
2) Change all uppercase letters file names into lowercase.
3) Find all .m4a files in my music directory && convert them into .mp3 format
4) Remove the old .m4a files.
I understand there is probably software out there, already designed to do this, but I am just writing this as a programming exercise to learn better.
Below is what I have come up with so far. Bear with me if there is something stupid I've written here -- I'm still learning.
Anyhow, I am worried about running any scripts that I have written that rename or remove files, because I am not sure how things are interpolated in the backticks before running the command (backticks being the little tilted single-quote looking things around the command to be run...), and don't want a weird character to be fed into the regex, and have it start wiping out files I don't want it to.
Here is what I have so far:
Code: |
#!/usr/bin/perl -w
use File::Find;
$music_dir="/mnt/storage/music";
find(\&Wanted, $music_dir);
sub Wanted{
$_ eq "." and next;
$_ eq ".." and next;
my $new_filename = $_;
#Change all letters to lowercase
$new_filename =~ s/(\w+)/\L$1/g;
#Change whitespace to underscore
$new_filename =~ s/(\s+)/_/g;
rename $File::Find::name, "$File::Find::dir/$new_filename";
#Then convert it to the proper format && remove the old copy.
if ($new_filename =~ /(\w+)[.]{1}m4a$/){
`faad $File::Find:dir/$new_filename`
or die "Couldn't transcode $File::Find::dir/$new_filename from .m4a to .wav: $!";
`lame -m j $new_filename $1.mp3`
or die "Couldn't transcode $File::Find::dir/$new_filename from .wav to .mp3: $!";
`rm $File::Find::dir/$new_filename`
or die "Couldn't remove $File::Find::dir/$new_filename: $!";
`rm $File::Find::dir/$1.wav`
or die "Couldn't remove $File::Find::dir/$new_filename: $!";
}
}
|
Does this look like it will work? I am especially worried about my regular expressions. Do they look sensible? Anybody have any suggestions on how to make it work better?
Also, if anyone has some good documentation on what goes on inside those backticks, I'd love to hear all about it...
Thanks,
Mr. Snorfles |
|
Back to top |
|
|
embobo Guru
Joined: 19 May 2003 Posts: 311
|
Posted: Mon Aug 20, 2007 10:55 pm Post subject: |
|
|
Code: |
sub Wanted
{
-f $_ or return; # make sure it is a file
$new =~ s/\s+/_/g; # replace whitespaces with _
my $new = lc; # lowercase ($_ implicit; see perldoc -f lc)
$new eq $_ or rename $_, $new;
$_ =~ /\.m4a$/ or return; # convert only entries that end in .m4a
my $mp3 = $new;
$mp3 =~ s/m4a$/mp3/; # change extension from m4a to mp3
system "faad $new | lame -m j - $mp3"; # use pipe
if ($? != 0) {
warn "faad | lame failed\n";
return;
}
unlink $new;
}
|
Edit: I fail at reading. |
|
Back to top |
|
|
embobo Guru
Joined: 19 May 2003 Posts: 311
|
Posted: Mon Aug 20, 2007 11:20 pm Post subject: Re: Script To Rename && Convert Music Files |
|
|
I'll make comments on your code too.
Code: |
$_ eq "." and next;
$_ eq ".." and next;
|
You are not in a loop. Use return instead.
Code: |
my $new_filename = $_;
#Change all letters to lowercase
$new_filename =~ s/(\w+)/\L$1/g;
|
I find "my $new_filename = lc $_" more succinct. There is no need to match on words (\w+). Even "s/(.*)/\L$1/" would be better.
Code: |
$new_filename =~ s/(\s+)/_/g;
|
No need for ()'s.
Code: |
rename $File::Find::name, "$File::Find::dir/$new_filename";
|
You are chdir'ed into the the dir. You could just use $_ and $new_filename here.
Code: |
if ($new_filename =~ /(\w+)[.]{1}m4a$/){
|
This is awkward. If you want to split the name into two parts (blah)(.m4a) I'd do "/(*.)\.m4a$/" instead or use File::Basename.
Code: |
`faad $File::Find:dir/$new_filename`
or die "Couldn't transcode $File::Find::dir/$new_filename from .m4a to .wav: $!";
`lame -m j $new_filename $1.mp3`
or die "Couldn't transcode $File::Find::dir/$new_filename from .wav to .mp3: $!";
|
No need to use backticks a simple system call would be ok. It is possible to pipe these two commands.
Also, I don't like using $1 this far from the match. I'd assign it to a variable right after the match.
Code: |
`rm $File::Find::dir/$new_filename`
or die "Couldn't remove $File::Find::dir/$new_filename: $!";
`rm $File::Find::dir/$1.wav`
or die "Couldn't remove $File::Find::dir/$new_filename: $!";
}
}
|
You could use the perl builtin unlink for this.
Does this look like it will work? I am especially worried about my regular expressions. Do they look sensible? Anybody have any suggestions on how to make it work better?
Also, if anyone has some good documentation on what goes on inside those backticks, I'd love to hear all about it...
Thanks,
Mr. Snorfles[/quote] |
|
Back to top |
|
|
mistersnorfles n00b
Joined: 03 Aug 2007 Posts: 32
|
Posted: Mon Aug 27, 2007 1:53 pm Post subject: |
|
|
Thank you very much for the response -- I ended up getting everything working. Appreciate the assistance...
--snorfles |
|
Back to top |
|
|
|