Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

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

by shadowsong (Monk)
on Sep 08, 2015 at 22:15 UTC ( #1141372=note: print w/replies, xml ) Need Help??


in reply to Re^2: 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.

Brandon,

Let's looks at the solution you have come up with; but before we do - just a quick note:

#!/usr/bin/perl -slw use strict; use warnings;

The use warnings; pragma is redundant if you supply the -w switch
--

Now, looking at your solution we can see that you've opened a target directory and proceeded to read its contents via the excerpt below:

opendir DH, "Y://perlscripts2/software/perl2/music" or die $!; # open +current directory while($_ = readdir(DH)){ # don't evaluate special dirs '.' & '..' next if $_ eq "." or $_ eq "..";

What comes next is a bit peculiar..

if ($_ =~ /\.txt/){ chomp $_; my ($artist, $song_title) = split '-', $_, 3; $length{$artist}{$artist} = $artist; $length{$artist}{$song_title} = $song_title; print "$_"; # print this file/directory's name }

What you're saying above is to match filenames with ".txt" in them. Are you sure this is what you want to do? Do you have ".txt" embedded within your music filenames?

Notwithstanding your expectations of the existence of a ".txt" filename which you'd like to process in your music files directory - you should be doing that check within the 2nd if (-f $_) conditional; so you only check legitimate regular files for the ".txt" string.

Here's a small script I wrote to process some flac files within one of my music directories (which is devoid of any ".txt" files)

#! perl -slw use strict; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my ($id,$songs_ref,$artists_ref,$albums_ref,%songs,%artists,%albums); opendir DH, "D:/music/Alice In Chains/2001 - Greatest Hits" or die $!; # open current directory while($_ = readdir(DH)){ # don't evaluate special dirs '.' & '..' next if $_ eq "." or $_ eq ".."; # music files in this directory are *.flac files with the # naming style: <track#> - <band> - <album> - <track.flac> # no need to check stat info - we're processing files that # end in .flac (notice the end-of-line match char '$'?) if (m{\.flac$}){ # tip: m{..} is another way of saying /../ # add .flac to the split pattern so that it is not # included in our "<track>" field my ($track_num, $band, $album, $track) = split / \- |\.flac/; # increment our hash ref id so we don't overwrite entries $id++; # ------------------------------------------------------- # Example Using Hash References # ------------------------------------------------------- $songs_ref->{$id}->{TITLE} = $track; $songs_ref->{$id}->{ARTIST} = $band; $songs_ref->{$id}->{FAVOURITE} = 1 if $track eq 'Would'; $songs_ref->{$id}->{TRACK_LENGTH} = undef; # to do later $artists_ref->{$id}->{NAME} = $band; $artists_ref->{$id}->{SONGS}->{TITLE} = $track; $artists_ref->{$id}->{SONGS}->{ALBUM} = $album; $albums_ref->{$id}->{ARTIST} = $band; $albums_ref->{$id}->{NAME} = $album; $albums_ref->{$id}->{SONGS}->{TITLE} = $track; $albums_ref->{$id}->{SONGS}->{TRACK_NUM} = $track_num; # ------------------------------------------------------- # Example Using Hashes # ------------------------------------------------------- $songs{$id}{TITLE} = $track; $songs{$id}{ARTIST} = $band; $songs{$id}{TRACK_LENGTH} = undef; # to do later $artists{$id}{NAME} = $band; $artists{$id}{SONGS}{TITLE} = $track; $artists{$id}{SONGS}{ALBUM} = $album; $albums{$id}{ARTIST} = $band; $albums{$id}{NAME} = $album; $albums{$id}{SONGS}{TITLE} = $track; $albums{$id}{SONGS}{TRACK_NUM} = $track_num; } } closedir DH; # use perl's object data serializer to view our data print Dumper $songs_ref; print Dumper $artists_ref; print Dumper $albums_ref; print Dumper \%songs; print Dumper \%artists; print Dumper \%albums; __END__

I would like to focus on why it is you're not getting those ".txt" files open for processing, but to do that we need to establish which files are in the directory that you're reading from? Have a look at the example provided and if you find it's still necessary to open and read some kind of ".txt" file - please provide us with the output of dir "Y://perlscripts2/software/perl2/music"

Good luck!

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

    Shadowsong, here is the output of my directory. I know that music files don't consist of .txt extensions, but this is what I was asked to do for the assignment. So, I made these files names up and went with this type. Inside the files there is supposed to one line that contains the album, minutes, seconds, and genre each separate by ":". The Sun and the Moon:3:47:Alternative

    OUTPUT of DIRECTORY:<\p>

    The Bravery-Believe.txt

    output for file: The Bravery-Believe.txt

    The Bouncing Souls-True Believers.txt

    output for file: The Bouncing Souls-True Believers.txt

    The Kickdrums-Atonement.txt

    output for file: The Kickdrums-Atonement.txt

    I'm assuming that this:

    if ($_ =~ /\.txt/){ chomp $_; my ($artist, $song_title) = split '-', $_, 3; $length{$artist}{$artist} = $artist; $length{$artist}{$song_title} = $song_title; print "$_"; # print this file/directory's name

    Could be part of this:

    open FH, "<$_" or die $!; print "output for file: $_\n"; while (my $line = <FH>) { print $line; chomp $line; if ($line =~ /\.txt/){ my $artist; my ($album, $minutes, $seconds, $genre) = split ':', $line, 4; $length{$artist}{album} = $album; $length{$artist}{minutes} = $minutes; $length{$artist}{seconds} = $seconds; $length{$artist}{genre} = $genre; print $album, "\n"; }

    So, I'm still trying to open the FH of the .txt file and read the contents to get the total amount of the song length for each line and print it out. "Saying this Artist has a total amount of Music". I really appreciate your guidance and patience with me. I know I am a newby at this, but I'm willing to put the time in to learn and get the most out of this language. Thanks, Brandon

      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!

        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

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2019-06-20 21:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (91 votes). Check out past polls.

    Notices?