LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-18-2007, 10:18 PM   #1
mistersnorfles
Member
 
Registered: Aug 2007
Distribution: Gentoo 2007.0
Posts: 51

Rep: Reputation: 15
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

Last edited by mistersnorfles; 08-18-2007 at 10:24 PM.
 
Old 08-19-2007, 03:39 PM   #2
rickh
Senior Member
 
Registered: May 2004
Location: Albuquerque, NM USA
Distribution: Debian-Lenny/Sid 32/64 Desktop: Generic AMD64-EVGA 680i Laptop: Generic Intel SIS-AC97
Posts: 4,250

Rep: Reputation: 61
http://www.linuxquestions.org/questi...d.php?t=555911

That thread addresses some of your questions. You situation is a little different because you're dealing with m4a files, but it looks to me like you have that under control.

The "backtick" function has been deprecated, and (for me) using the new format makes it easier to understand. Replace the backtics with $() ... like this: $ echo $(uname -r)
 
Old 08-19-2007, 06:25 PM   #3
mistersnorfles
Member
 
Registered: Aug 2007
Distribution: Gentoo 2007.0
Posts: 51

Original Poster
Rep: Reputation: 15
Thanks a bunch rickh, I'd never heard of the $() function. I'll look into that...

Thanks for the help!

--Mr. Snorfles
 
Old 08-19-2007, 08:02 PM   #4
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.6, Centos 5.10
Posts: 16,462

Rep: Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119
Instread of a regex, I'd used the lc() fn to convert case.
http://perldoc.perl.org/functions/lc.html
Also, mandate
use locale;
at the top of your prog to deal with any accented chars (even if you don't have any, it's good practice)
Also,
use strict;
forces declarations and traps some other possible errors. Again, it's best practice to use that and the "-w" switch together. They do different checks.
To do a test compile without running prog do
perl -wc yourprog.pl
which will just do a test compile and syntax check.
The other thing is to comment out the rm cmds until you've tested the rest.
Use the unlink() fn instead of rm.
http://perldoc.perl.org/functions/unlink.html

HTH
 
Old 08-19-2007, 08:34 PM   #5
mistersnorfles
Member
 
Registered: Aug 2007
Distribution: Gentoo 2007.0
Posts: 51

Original Poster
Rep: Reputation: 15
Yeah I figured there was a lowercase function, but I just didn't know what it was called. I agree, lc() will definitely be an easier way to do this. Thanks Chris.

By the way, as fan as using unlink() vs rm, what are the benefits?

Same with $() vs `command` -- why is the former the better choice?

Thanks for the help folks.

--Mr. Snorfles

Last edited by mistersnorfles; 08-19-2007 at 08:38 PM. Reason: Found the answer in the link you gave me...
 
Old 08-19-2007, 08:47 PM   #6
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.6, Centos 5.10
Posts: 16,462

Rep: Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119
unlink - give it a scalar containing full path, or just filename if perl prog is in same dir as file to remove.
If you don't require to trap/gather the output from external cmds, you can use system() http://perldoc.perl.org/functions/system.html
The doc page explains this more fully.

Personally, I'd use something like the following instead of File::Find:
Code:
opendir(DIR, $dirname) or die "can't opendir $dirname: $!";
while (defined($file = readdir(DIR))) 
{
    next if $file =~ /^\.\.?$/;     # skip . and ..
    # do something with "$dirname/$file"
}    
closedir(DIR);
but TMTOWTDI, YMMV
 
Old 08-19-2007, 09:48 PM   #7
mistersnorfles
Member
 
Registered: Aug 2007
Distribution: Gentoo 2007.0
Posts: 51

Original Poster
Rep: Reputation: 15
Thanks again for all the help. I made the suggested modifications --except for $() which I couldn't figure out -- and everything worked wonderfully. Here was the script I ended up running:

Code:
#!/usr/bin/perl -w
use File::Find;
use locale;
use strict;

my $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=lc($new_filename);

	#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$/){
	  my $filename_no_ext = $1;
          
         (system("faad", "$File::Find::dir/$new_filename") or $new_filename =~ s/m4a$/wav/)
           or die "Couldn't transcode $File::Find::dir/$new_filename from .m4a to .wav: $!";
		   
	  system("lame", "-m","j", "$new_filename", "$filename_no_ext.mp3")
	   and die "Couldn't transcode $File::Find::dir/$new_filename from .wav to .mp3: $!";
		
	  unlink("$File::Find::dir/$new_filename")
           or die "Couldn't remove $File::Find::dir/$new_filename: $!";
   	  unlink("$File::Find::dir/$filename_no_ext.m4a")
           or die "Couldn't remove $File::Find::dir/$new_filename: $!";
	}
}
Went off without a hitch...

Thanks,
Mr. Snorfles

Last edited by mistersnorfles; 08-19-2007 at 10:01 PM.
 
Old 08-20-2007, 08:03 PM   #8
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.6, Centos 5.10
Posts: 16,462

Rep: Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119Reputation: 2119
I assume this
(system
is a typo?
Also,
and die "
should be 'or die' ?
 
  


Reply

Tags
backticks, conversion, m4a, mp3, perl, renaming, rm


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
m4a convert - rename script webvolutionary Linux - General 1 11-21-2006 07:49 AM
SCRIPT: Convert & Burn to DVD bukzor Linux - General 2 05-13-2006 01:24 AM
Phục hồi dữ liệu bị mất???, cứ pollsite General 1 06-27-2005 12:39 PM
Problem with my sound card.. can't play video & music files! MESShY Linux - Newbie 5 04-29-2005 08:29 PM
in linux & c/c++: how do I convert an ascii string to utf8 & vice versa? davidh_uk Programming 2 02-06-2005 05:55 PM


All times are GMT -5. The time now is 06:01 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration