Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Re^5: I need help with opening a directory and reading files in that directory.

by shadowsong (Monk)
on Sep 09, 2015 at 09:37 UTC ( #1141403=note: print w/replies, xml ) Need Help??

in reply to Re^4: I need help with opening a directory and reading files in that directory.
in thread I need help with opening a directory and reading files in that directory.

Ahh, now I see what you're trying to do...

Remember when we warned things could get hairy? OK, firstly - please consider what Anonymous Monk said very carefully..

OK, now that we know what your files look like, lets focus on why we're not opening/processing them. 2 things:

  • Are the files being tested accessible to the script? i.e. does the script live in the same directory as they do? Y://perlscripts2/software/perl2/music. If it doesn't - you'll need to consider how to supply your if (-f ...) conditional with the absolute path to the file you're testing OR change directory to the same directory as the files you're testing prior to testing them (see chdir)
  • Once you've addressed the incorrectly placed close FH function call - mentioned by Anonymous Monk above (i.e. move it out of your while loop so you don't close a filehandle while working with it), I'd like you to reassess where you'd planned to put the if (/\.txt$/) conditional. hint: should we be testing a file after opening it?

Have another crack at it and see what you come up with. Larry Wall said that Perl is an empirical science - you learn things about it by trying it out.

Keep up the good work!

Replies are listed 'Best First'.
Re^6: I need help with opening a directory and reading files in that directory.
by brawal128 (Novice) on Sep 09, 2015 at 14:46 UTC

    Shadowsong," does the script live in the same directory as they do?"

    No the .pl file is in the same folder as perlscripts2, but the .txt files are in a subfolder of the perlscripts2. Which would be /software/perl2/music/*. The .pl does not live in the same place as the .txt files I am trying to read.

    Here is what I came up with to test the output....

    #!/usr/bin/perl -l use strict; use warnings; use Data::Dumper; my ($id,%length); my $fh1 = "The Bouncing Souls-True Believers.txt"; opendir DH, "Y:/perlscripts2/software/perl2/music" or die $!; # open c +urrent directory while($_ = readdir(DH)){ # don't evaluate special dirs '.' & '..' next if $_ eq "." or $_ eq ".."; print "$_"; # print this file/directory's name } # as a by-product of readdir; use the file's stat info # to check whether this is indeed a regular file we can # open for reading/further processing if ($_ = $fh1) { open FH, "<$_" or die $!; print Dumper $_; print "output for file: $_\n"; while (my $line = <FH>) { chomp $line; print $line; if ($line=~ /\.txt/){ my ($artist, $song_title) = split '-', $line, 3; $length{$id}{artist} = $artist; $length{$id}{song_title} = $song_title; } elsif (my $row =~ /\:/){ chomp $row; my ($album, $minutes, $seconds, $genre) = split ':', $ +row, 4; $length{$id}{album} = $album; $length{$id}{minutes} = $minutes; $length{$id}{seconds} = $seconds; $length{$id}{genre} = $genre; } else{ print "Could not open file $_\n"; } }close FH; } foreach my $artist ( sort keys %length ) { print "$length{$id}{artist} is the name of the Artist\n"; print "$length{$id}{song_title} is the name of the song\n"; print "Album is $length{$id}{album} \n"; print "Album minutes is $length{$id}{minutes} \n"; print "Album seconds is $length{$id}{seconds} \n"; print "Album genre is $length{$id}{genre} \n"; }

    The output is The Bouncing Souls-True Believers.txt, but it is not reading the file, chomping the lines, creating the hashes, and not getting the .txt files information that I need. I hope that I will figure this out soon. I'm literally beating my head against the my keyboard.

    I'm going to be real honest. I'm starting to get confused because I have been trying to do different things and test them out. I have spent a lot of time trying to figure out how to get to the folder "music" and read the .txt files in the music folder, and then do something with them. You guys have provided some good information, but I still can't figure this out. I'm not giving up, but just need some more explanation on this.

    P.S. Not looking for anyone to do the work for me. I just want to understand exactly what is going on.

    Thanks, Brandon


      Welcome to the wonderful world of programming - don't be discouraged, this happens to the best of us

      OK, from what you have posted - you're main problem is a file path problem. My advice?

      start fresh
      but leave your current script as-is so you can see where you're coming from. Have a look at the snippet below which shows how I have used chdir() to handle the file path issue:

      #! perl -slw use strict; use Data::Dumper; my ($album_id,$track_id,$filepath,%music); $filepath = 'Y:/perlscripts2/software/perl2/music' opendir DH, $filepath or die $!; # magic one-liner to "fix" your path problems chdir($filepath); while(readdir(DH)){ # don't evaluate special dirs '.' & '..' # or anything that doesn't end in .txt next if $_ eq "." or $_ eq ".." or $_ !~ /\.txt$/; # explicitly test this item to see if it's a # regular file and if it's readable (notice the # use of the default filehandle test var '_') next unless -f $_ and -r _; # arrival here signifies we have a readable, # regular file. Extract its contents into a hash open FH, '<', $_ or die "could not open file: $_\n"; # use the actual filename to pull the album & artist my ($name, $artist) = split /\-|\.txt/; $album_id++; $track_id = 0; $music{$album_id}{ALBUM} = $name; $music{$album_id}{ARTIST} = $artist; while (my $line = <FH>) { # the lines of this file are of the format # <track>:<minutes>:<seconds>:<genre> my ($track, $minutes, $seconds, $genre) = split /\:/, $line; $track_id++; $music{$album_id}{$track_id}{TRACK}{TITLE} = $track; $music{$album_id}{$track_id}{TRACK}{DURATION} = [$minutes,$seconds +]; $music{$album_id}{$track_id}{TRACK}{GENRE} = $genre; } close FH; } print Dumper \%music; __END__

      You're almost there mate. Keep at it.

        Shadowsong, I appreciate all of the help that you have given me. The below code is what I was able to get to work and print out successfully. I did use some of the items that presented in your previous post. My issues were around setting up the hashes and keys. But, we will see what the instructor says about what I came up with. It is nice to know that there are folks out there willing help a newbie such as myself.

        #!usr/bin/perl -l use strict; use warnings; use Data::Dumper; my ($artist, $song_title, $filepath, %length,); $filepath = 'Y:/perlscripts2/software/perl2/music'; opendir DH, $filepath or die $!; chdir($filepath); while ($_ = readdir(DH)) { next if $_ eq "." or $_ eq ".." or $_ !~ m/\.txt$/; next unless -f $_ and -r $_; open FH, '<', $_ or die "could not open file: $_\n"; my ($artist, $song_title) = split /\-|\.txt/; $length{$artist}{artist} = $artist; $length{$artist}{song_title} = $song_title; while (my $line = <FH>){ my ($album, $minutes, $seconds, $genre) = split ':', $line, 4; $length{$artist}{album} = $album; $length{$artist}{minutes} = $minutes; $length{$artist}{seconds} = $seconds; $length{$artist}{genre} = $genre; } close FH; } foreach my $artist ( sort keys %length ) { print "$length{$artist}{artist} has a total $length{$artist}{m +inutes}:$length{$artist}{seconds} of music.\n"; }

        Thanks, Brandon

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1141403]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2019-05-24 06:49 GMT
Find Nodes?
    Voting Booth?
    Do you enjoy 3D movies?

    Results (147 votes). Check out past polls.

    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!