juro has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm fairly new to perl, and have difficulties to get the parent diretory name.
What I want to do is:

I have a very large collection of music files from which a vast amount neither is tagged correctly or tagged at all.
Also their file name is not right. But I do now that the directory structure is right. The 1st dir is artist, this contains subdirs with the albums, and the filenames contains at least the trackname but sometimes also other info.
(ie: /Celtic Frost/Into The Pandemonium/02\ -\ Mesmerized.mp3

So I need a script that reads a files name, the name of it's parent directory and the directory above that, and than examins the file name to substract the trackname. That results in 3 variabels from which I can correctly rename the file, and tag the file.

From wihtin the example directory above I tried :
my $artistdir=opendir(DIR, '..'); my $albumdir=opendir(DIR, '.'); print "$artistdir\n"; print "$albumdir\n";
Clearly that does not work.

Replies are listed 'Best First'.
Re: how to get the parent directory name?
by reneeb (Chaplain) on Dec 08, 2006 at 11:50 UTC
    #!/usr/bin/perl use strict; use warnings; use Cwd; print Cwd::realpath('..');

      Bzzzt! Crash! This is the sound of the cross-platform compatibility police knocking at your door!

      I feel obliged to point out that there is a module that encapsulates the concept of parent directory. Thus your code becomes:

      use strict; use warnings; use Cwd; use File::Spec; print Cwd::realpath(File::Spec->updir);

      When code begins to involve both Cwd and File::Spec, you know it's time to look at Path::Class (see elsewhere in this thread).

      • another intruder with the mooring in the heart of the Perl

Re: how to get the parent directory name?
by jbert (Priest) on Dec 08, 2006 at 12:07 UTC
    Or do it the other way. Run your script at the top level of your music and use relative paths below that:
    use File::Spec qw/splitdir/; my @files = glob "*/*/*"; foreach my $file (@files) { my ($artist, $album, $track) = File::Spec->splitdir($file); # Do something to $file using these vars and a module to # get/set tags }
    Remember, your current working dir is a global variable, which lots of code relies on (all your open calls, for instance). I've always regretted chdiring around in a script. It's generally easier to work with relative paths from where you are.

      For cases like this, I work from the top, and just keep track of where I've been:

      Yes, it seems like it's more work, but it allows you do special handling as you enter/leave each directory -- maybe you want to create playlists for each artists, etc. And I'm actually dealing with millions of files (scientific data, not music albums)

      okay ... I don't actually use code like that -- it's too repetitive ... I use recursive functions (as it's much more than 3 levels deep) and a dispatch table for the directories that need to be handled in a special manner ... but the above at least explains the basic methodology and should be easier to follow.

        Thanks all of you for the resposes!

        I used this code ast a starting point, and I'm almost there, thanks!

        I had to change
        next if (-D
        into
        next if (!-d
        I guess that's just my version of perl?
Re: how to get the parent directory name?
by xdg (Monsignor) on Dec 08, 2006 at 12:56 UTC

    Yet another way to do it:

    use Path::Class qw(dir); my $dir = dir(); # current directory my $parent = $dir->parent; # or more directly $parent = dir()->parent;

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: how to get the parent directory name?
by leocharre (Priest) on Dec 09, 2006 at 04:55 UTC

    I just put on cpan a module that might be of use with this kind of thing. It's File::PathInfo

    With it you could quickly get the file's location (the parent directory for a file)..

    use File::PathInfo; my $i = new PathInfo; $i->set('/absolute/path/to/your.mp3'); my $parent_directory = $i->abs_loc;