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

I am trying to parse this path but because it is a directory of subdirectories the last part of the path is variable. I want to assign the last directory in the path a variable so I can print it later on but I've had no luck. Any help is greatly appreciated. Thanks!

#!/usr/bin/perl + #KDUX station METARS throughout a certain directory + + use strict; use warnings; use File::Find; use File::Basename; my($filename, $directories, $suffix) = basename("/d2/aschwa/archive_pr +oject/METAR_data/#lastdirectoryname"); my @folder = ("/d2/aschwa/archive_project/METAR_data/"); open(OUT , '>',+ 'KDUX_METARS.txt') or die "Could not open $!"; + +print OUT "Station, Day/Time, Obs Type, Wind/Gust (Kt), Vis (SM), Sky +, T/Td (C), Alt, Rmk\n"; print STDOUT "Finding METAR files\n"; my $criteria = sub {if(-e && /^2012/) { open(my $file,$_) or die "Could not open $_ $!\n"; while(<$file>) { print OUT $lastdirectoryname, $_ if /KDUX ....55Z|KDUX +....05Z/; } } + }; + find($criteria,@folder); + close OUT;

Replies are listed 'Best First'.
Re: I humbly ask for your help with parsing
by atcroft (Abbot) on Oct 30, 2013 at 20:09 UTC

    I think File::Spec's catdir(), splitdir(), catpath(), and splitpath() functions may be what you are looking for. You may use splitpath() to break the name apart, splitdir() to break the directory into a list, push() the desired directory name onto the end, then catdir() to reassemble the directory path, then catpath() to build the full name.

    Hope that helps.

      ++ atcroft -- File::Specdoes the job:

      #!/usr/bin/perl use strict; use warnings; use File::Spec; { my $pathName = "/usr/tmp/booger/test.dat"; my $baseName = ExtractLastDir($pathName); print "Result is $baseName\n"; } exit; sub ExtractLastDir { my ($fullName, @extraStuff) = @_; if (!defined $fullName) { $fullName = ''; } my ($volumeName, $directoryPath, $fileName) = File::Spec->splitpat +h($fullName); my @directoryNames = File::Spec->splitdir($directoryPath); # Grab the last element from the directory -- but it is probably b +lank my $lastDirectory = pop @directoryNames; # So if it is blank, get the next one if ($lastDirectory eq '') { $lastDirectory = pop @directoryNames; } return $lastDirectory; } __END__ C:\Steve\Dev\PerlMonks\P-2013-10-30@1354-BaseDir>basedir3.pl Result is booger
Re: I humbly ask for your help with parsing
by marinersk (Priest) on Oct 30, 2013 at 20:00 UTC

    I can't get your code to run, and I don't think it's because I'm on a Windows system (but I could be wrong):

    C:\Steve\Dev\PerlMonks\P-2013-10-30@1354-BaseDir>basedir.pl Global symbol "$lastdirectoryname" requires explicit package name at C:\Steve\Dev\PerlMonks\P-2013-10-30@1354-BaseDir\basedir.pl line 22. Execution of C:\Steve\Dev\PerlMonks\P-2013-10-30@1354-BaseDir\basedir. +pl aborted due to compilation errors.

    Are you trying to extract the last directory name out of a full pathname? Example:

    my $pathName = "/usr/tmp/booger/test.dat";
    my $baseName = ExtractLastDir($pathName);
    print "Result is $baseName\n";

    And you would expect:

    Result is booger

    Is that your goal?

      That is exactly my goal. Sorry I wasn't very clear. There are a series of dated subdirectories (i.e. "20120405") underneath the directory "METAR_files" that are searched for a string and printed when that string is found. I just need to take the directory that the script is found in and print it with the script. The path name is: /d2/aschwa/archive_project/METAR_data/ and the subdirectories are "20110101","20110102","20110103", etc. I want to get the subdirectory name. Thank you so much for your help.

Re: I humbly ask for your help with parsing
by Lennotoecom (Pilgrim) on Oct 30, 2013 at 23:46 UTC
    $_ = '/usr/local/www/someth/file.cfg'; print "$1\n" if /.+\/(\w+)\//;
    no?
      The main benefit of matured modules is they handle corner cases you might have overlooked. Your code would, I agree, work most of the time, but if you get an odd directory name with a slash in it, she fails:

      $_ = '/usr/local/www/"something/other"/"This file/data thing.cfg"'; print "$1\n" if /.+\/(\w+)\//; www
        I agree, it's just,
        if the author's task is to thrash through some ordinary-named directories
        maybe he doesn't need all this module-stuff.
Re: I humbly ask for your help with parsing (Path::Tiny/File::Find::Rule)
by Anonymous Monk on Oct 30, 2013 at 22:53 UTC

    #!/usr/bin/perl --
    use strict; use warnings;
    use Path::Tiny qw/ path /;
    use File::Find::Rule qw/ file /;
    my @files = find( -file => name => qr{\.pl$} => in => $thisdironly, maxdepth => 1 );
    my @dirs = find( -file => name => qr{metar} => in => \@startdirs );
    my $kduxout = path('KDUX_METARS.txt')->openrw_utf8;
    print $kduxout "$_\n" for @files, @dirs;