I’m going to embarrass myself today, and post some hack-ish Perl code using recursion. Actually, because the code is only 35 lines, I think it turned out actually fairly well, but as I am a Perl n00b, I am sure that the experts out there will disagree with the quality of the code.
First and foremost, I have a global variable used as a counter. I know that this is a BIG NO-NO, but, because the code is only 35 lines in length, I’m not too worried. I do recognize, though, that passing the counter by reference through the recursive function PrintFiles() would probably be the better way to handle that, but then, that’s just making things a bit more difficult than I care at this point.
What does the program do? It should be fairly obvious: it runs through a root directory structure, looking for OGG Vorbis files, counting them, and printing the results to another text file for inventory. Basic, gets the job done, and without a lot of fanfare. The code should be self-evident, but I’m anal about commenting code, so redundant comments are placed throughout. The program was just an exercise for me to:
- Increase my ability to do simple recursion.
- Learn recursion using Perl.
- Create an inventory of my music.
Anyway, here’s the code:
#!/usr/bin/perl -w open(OUT, ">oggfiles.txt"); # Create the file to read to $counter = 0; # Global variable (no-no)!! :) sub PrintFiles # Recursive function for printing dir contents { my ($indent) = @_; # Keep track of indentation opendir(MD, "./"); # Start looking through local directory foreach my $file (sort readdir MD) # Start a loop going through each dir sorted { unless($file =~ m/^\./ || $file =~ m/^ogg/) # Prevent an infinite loop, don't worry about hidden (.*), oggdir.pl and oggfiles.txt files { $counter++ if $file =~ m/\.ogg$/; # Keep a counter for every ogg file print OUT $indent . $file . "\n"; # Print dir contents to a file if (-d $file) # If a directory { chdir $file; # Change to the directory PrintFiles("$indent "); # Call the recursive function again, incrementing the ident chdir "../"; # Change back } } } closedir(MD); # Close the dir } PrintFiles(""); # First call of the recursive function, with no spaces for indentation print OUT "\nCurrent number of music files: " . $counter . "\n\n"; close(OUT); # Close file written to

{ 4 } Comments
When I ran this I got a file full of data that did *not* include ogg files.
I spent more time than I should have trying to figure out why this was. I never did figure it out. I’m assuming you were able to make the code work the way you wanted it to. From what I can tell though, it looks ok. A global counter variable in this circumstance isn’t really a bad thing.
I know you’re doing this to learn recursion, at least a better understand of it in perl, but I can’t just let this pass without pointing out File::Find.
File::Find will take care of most of the heavy lifting for you.
Some notes:
Let the shell do the hard work. Why take the trouble to open a file when
you can redirect it? Call it like
This bit of code prints out every single directory name, regardless of
whether or not there is an ogg file in it or its children. You’d need to
store the data and then filter it once all the data was gathered.
The ‘preprocess’ portion of the code is called after each readdir with the
file list passed in. This allows us to set up the indent variable and
filter out the ‘hidden’ directories.
The ‘postprocess’ portion of the code is called after each directory has
been processed (i.e., the list returned by preprocess has been iterated
through). This allows us to trim the indent variable.
The ‘wanted’ portion of the code is called for every single file found in
the tree.
I’ll have to give that bit of code a look over when I get to work. File::Find looks like it will do exactly what I need.
I don’t know why you were getting files that were everything but *.ogg files. Looking over the code, everything is perfect. Maybe I’m missing something from the copy/paste.
oh, you know you want to just use:
find . -name "*.ogg"I’ve unleashed a script inspired by your approach to recursivity here:
http://www.chrisblanc.org/blog/?p=77
It’s a simple linefeed filter. By the way, don’t OGGs sound better than other file formats at the same bitrate? Amazing compression.
{ 2 } Trackbacks
[...] took my Perl script that I wrote some time ago, and rewrote it in Python. The exercise of the initial Perl script, was to get a better handle on [...]
[...] took my Perl script that I wrote some time ago, and rewrote it in Python. The exercise of the initial Perl script, was to get a better handle on [...]
Post a Comment