From: Patrick H. on
Hi, I am toying around with the directory operations chapter of
"Learning Perl" and ran into a bit of a snag.

I am trying to open a directory, output all the -f files to a @files
array and all the -d files to a @folders array. The problem is it
seems to only work for the first instance of readdir I use; they both
work individually when I comment the other out, but when I have them
both only the first array is populated. Do I need to closedir and then
opendir again, or is there a way for me to reset the cursor (if that
is even the right terminology)?

Below is my code, and advice would be appreciated.

Patrick H.


#!/usr/bin/perl -w
use strict;

# folder to scan
my $folder = 'c:/';

# open folder
opendir C_DRIVE, $folder or die "problem reading $folder: $!";

my @files = grep { -f "$folder/$_" } readdir(C_DRIVE); # all
files
my @folders = grep { -d "$folder/$_" } readdir(C_DRIVE); # all
folders

# close folder
closedir C_DRIVE;

# test results
print "your files: @files\n";
print "your folders: @folders\n";


From: J�rgen Exner on
"Patrick H." <patrickh(a)gmail.com> wrote:
>I am trying to open a directory, output all the -f files to a @files
>array and all the -d files to a @folders array. The problem is it
>seems to only work for the first instance of readdir I use; they both
>work individually when I comment the other out, but when I have them
>both only the first array is populated. Do I need to closedir and then
>opendir again, or is there a way for me to reset the cursor (if that
>is even the right terminology)?

You could try seek(). Although it is documented only for filehandles,
not directory handles. it just might work on directory handles, too.

>Below is my code, and advice would be appreciated.
>
[...]
># open folder
>opendir C_DRIVE, $folder or die "problem reading $folder: $!";
>
>my @files = grep { -f "$folder/$_" } readdir(C_DRIVE); # all
>files
>my @folders = grep { -d "$folder/$_" } readdir(C_DRIVE); # all
>folders

However a better approach would be to loop through all the files in a
single pass and assign them to @files or @folders as you read each
directory entry.

<sketch only, not actual code>

while (my $direntry = readdir (C_DRIVE))
if (-f $direntry) {push @files, $direntry};
if (-d $direntry) {push @folders, $direntry}
}


Or read then all into a one array, duplicate that array, and then filter

@folders = @files = readdir(...);
@folders = grep (-d ...., @folders);
@files = grep (-f ...., @files);

jue
>
># close folder
>closedir C_DRIVE;
>
># test results
>print "your files: @files\n";
>print "your folders: @folders\n";
>
From: Patrick H. on
On Feb 15, 11:26 pm, "Patrick H." <patri...(a)gmail.com> wrote:
> Hi, I am toying around with the directory operations chapter of
> "Learning Perl" and ran into a bit of a snag.
>
> I am trying to open a directory, output all the -f files to a @files
> array and all the -d files to a @folders array. The problem is it
> seems to only work for the first instance of readdir I use; they both
> work individually when I comment the other out, but when I have them
> both only the first array is populated. Do I need to closedir and then
> opendir again, or is there a way for me to reset the cursor (if that
> is even the right terminology)?
>
> Below is my code, and advice would be appreciated.
>
> Patrick H.
>
> #!/usr/bin/perl -w
> use strict;
>
> # folder to scan
> my $folder = 'c:/';
>
> # open folder
> opendir C_DRIVE, $folder or die "problem reading $folder: $!";
>
> my @files = grep { -f "$folder/$_" } readdir(C_DRIVE);      # all
> files
> my @folders = grep { -d "$folder/$_" } readdir(C_DRIVE);    # all
> folders
>
> # close folder
> closedir C_DRIVE;
>
> # test results
> print "your files: @files\n";
> print "your folders: @folders\n";

With the risk of looking like I'm talking to myself, I came up with a
different way of doing it through just one readdir - figured I would
post what my solution ended up being.

-Patrick

# scope variables
my (@files,@folders);

# read directory
while (my $name = readdir C_DRIVE) {
push @files, $name if -f "$folder/$name";
push @folders, $name if -d "$folder/$name";
}

From: Patrick H. on
On Feb 15, 11:42 pm, Jürgen Exner <jurge...(a)hotmail.com> wrote:
> However a better approach would be to loop through all the files in a
> single pass and assign them to @files or @folders as you read each
> directory entry.
>
> <sketch only, not actual code>
>
>         while (my $direntry = readdir (C_DRIVE))
>                 if (-f $direntry) {push @files, $direntry};
>                 if (-d $direntry) {push @folders, $direntry}
>         }


Jue, thank you very much for the input. I came up with a similar
approach before I read your post. Always glad to have someone else's
opinion confirm what I was thinking :) .

Thanks,
Patrick


From: John W. Krahn on
Patrick H. wrote:
> Hi, I am toying around with the directory operations chapter of
> "Learning Perl" and ran into a bit of a snag.
>
> I am trying to open a directory, output all the -f files to a @files
> array and all the -d files to a @folders array. The problem is it
> seems to only work for the first instance of readdir I use; they both
> work individually when I comment the other out, but when I have them
> both only the first array is populated. Do I need to closedir and then
> opendir again, or is there a way for me to reset the cursor (if that
> is even the right terminology)?

perldoc -f rewinddir


> Below is my code, and advice would be appreciated.
>
> Patrick H.
>
>
> #!/usr/bin/perl -w
> use strict;
>
> # folder to scan
> my $folder = 'c:/';
>
> # open folder
> opendir C_DRIVE, $folder or die "problem reading $folder: $!";
>
> my @files = grep { -f "$folder/$_" } readdir(C_DRIVE); # all
> files
> my @folders = grep { -d "$folder/$_" } readdir(C_DRIVE); # all
> folders

my ( @files, @folders );
while ( my $file = readdir C_DRIVE ) {
push @files if -f "$folder/$file";
push @folders if -d "$folder/$file";
}


> # close folder
> closedir C_DRIVE;
>
> # test results
> print "your files: @files\n";
> print "your folders: @folders\n";



John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway