Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

reading directories

by data (Monk)
on Sep 14, 2001 at 20:58 UTC ( #112462=perlquestion: print w/replies, xml ) Need Help??
data has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to access two directories and open files that match a particular pattern; then I was trying to read in the data from those files in to an array. Where am I going wrong. How can i read files in a directory(test1) and its sub-directory(test2) and put them in an array. The following is a portion of the code. THANKS
opendir(DIR,"/users/temp/test1"); while(defined (my $line = readdir(DIR))){ next if ($line =~ /^\./); . . chomp $line; @filedata = split /!/, $line; . . } closedir (DIR);

Edited: (footpad) 15 Sep. 2001, 20:02 PDT; 16 Sep. 2001, 03:02 GMT

Replies are listed 'Best First'.
Re: reading directories
by dga (Hermit) on Sep 14, 2001 at 21:10 UTC

    You could make an array of everything then grep out what you don't want.

    #!/usr/bin/perl use strict; my(@t1)=dirarray("test1"); #get everything my(@t2)=grep !/^\./, dirarray("test2"); #get everything but dot files sub dirarray { my($dir)=@_; my $dh; opendir($dh, $dir) or die "$0: Cannot open $dir for listing: $!\n" +; my(@files)=readdir($dh) or die "$0: Can not list files in $dir: $! +\n"; return(@files); }

    Then you can use the arrays as desired.

Re: reading directories
by higle (Chaplain) on Sep 14, 2001 at 21:17 UTC
    The way that your code is structured, the only file in the directory that will be analyzed is the first one, technically ".".

    try this:
    opendir(DIR, "/users/foo/") || die "Whoops!"; @bar = readdir(DIR); closedir(DIR) || warn "Unable to close DIR"; splice(@bar, 0, 2); #get rid of '.' and '..'
    And now, @bar contains all of the file names in directory '/users/foo/'. You can then use a foreach loop or whatever to analyze the contents of that array line by line.

    Hope that helps,

    Update: Feel free to omit the splice bit in the above snippet for possible portability concerns. (though, this bit has been an integral part of a batch process that has been running flawlessly on my HP/UX machine every day for the last year or so, the song may not be the same for other OS flavors). I thought I'd throw that in to clean up the data, but it's not necessary for the example. Tip o' the lid to merlyn.

    Update++: In addition, my little pre-lunch break, thirty-second hack (indeed, it was hacked together in the few seconds I had before my coworkers left me to starve) has recently become the subject of another thread... It was brought up that it had absolutely no error-checking, and indeed used a dubious hack to snip the dot and dotdot out of the array. I've replaced my nasty for loop with a nice, tidy splice command, and added perfunctory error checking to the opendir and closedir commands. I omitted those at first because I assumed they were rhetorical in such an abstract example. Assumption is the mother of all... etceteras. :)
      opendir(DIR, "/users/foo/"); @bar = readdir(DIR); closedir(DIR); for (1..2) {shift @bar;} #get rid of '.' and '..'
      There is no promise that the first two elements returned from a readdir are dot and dotdot, so this code is dangerously unportable. It might not even work on your own machine tomorrow.

      -- Randal L. Schwartz, Perl hacker

Re: reading directories
by suaveant (Parson) on Sep 14, 2001 at 21:32 UTC
    I may be misunderstanding but...
    @dir = </users/temp/test1>; push @dir, </users/temp/test1/test2>; @dir = grep !/^\.$/, @dir;
    though that will only work in perl 5.6.0 and above, I belive.... or if you wanted them in separate dirs it should be obvious enough how to change that

                    - Ant
                    - Some of my best work - Fish Dinner

Re: reading directories
by HamNRye (Monk) on Sep 15, 2001 at 01:33 UTC

    This will get all files from the two directories, and place their contents into an array. You can always regex the @filep array for specific extensions after you are done getting the directory listings.

    $dir1 = "/foo/bar1" $dir2 = "/foo/bar2" @filep; @fcontents; get_dir($dir1); get_dir($dir2); for (@filep) { my $fc = get_file($_); push @fcontents, $fc; } print "@fcontents"; sub get_dir { my $dir = shift ; opendir(DIR, $dir) || die "Cannot open dir. $!" ; my @files = grep !/^\.\.?$/, readdir DIR ; closedir DIR; for (@files) { $fn = join '/', ($dir, $_); push @filep, $fn; #return @filep ; } sub get_file { my $file = shift; local *IN; open (IN, "<$file") or die "Cannot read '$file': $!"; if (wantarray) { return <IN>; } else { return join '', <IN>; } }
      what if you want to avoid some files other than the dot files, like some other programs that you may have in the dir. And how would you just get file e.g., file.1,file.2, file.3 etc.

        I'm not sure exactly what you want to do....

        Basically, you have all of your file names in the array @files. You can use a do...for loop

        for (@files) { /\.txt/ && do { print; }; }

        This prints the name of all text files.

        for (@files) { !/\.txt/ && do { print; }; }

        This prints the names all non .txt files (note negation)

        <code> for (@files) { /^ignore?$/ && do { print; }; }

        Will skip all filenames beginning with ignore.

        You should be getting the idea. ~Hammy

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://112462]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2018-06-18 23:56 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (111 votes). Check out past polls.