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

Dearest monks, how do I read a list of text files from a particular directory into an array?

I am thinking of something like this.

#! /usr/bin/perl $dir = "/root/dir"; opendir(BIN, $dir) or die "Can't open $dir: $!"; while( defined ($file = readdir BIN) ) { @array = #####now I am stuck!!!!!! }
Am I doing this right?

Replies are listed 'Best First'.
Re: Read a list of files into an array
by blue_cowdawg (Monsignor) on Jun 22, 2007 at 14:48 UTC
        Am I doing this right?

    Here's a couple of ways you can go:

    # modification to code you already have.... while( $file=readdir BIN ){ push @array,$file; }
    or
    # a slightly different play.... # delete the while loop altogether and... @array = readdir BIN ;

    Keep in mind you are going to have the "." and ".." directory entries (current working directory and parent directory respectively) in your list and you need to have logic to eliminate those.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Read a list of files into an array
by Roy Johnson (Monsignor) on Jun 22, 2007 at 14:48 UTC
    Do you want the array to contain the names of all the text files in the directory? Something like:
    #! /usr/bin/perl use strict; use warnings; my $dir = "/root/dir"; opendir(BIN, $dir) or die "Can't open $dir: $!"; my @array = grep { -T "$dir/$_" } readdir BIN;

    Caution: Contents may have been coded under pressure.
Re: Read a list of files into an array
by citromatik (Curate) on Jun 22, 2007 at 14:49 UTC
    Dearest monks, how do I read a list of text files from a particular directory into an array?

    you can use the glob function:

    perl -e 'my @arr=glob ("*.*");print "$_\n" for (@arr)'

    HTH

    citromatik

    Update: Or even more compressed

    perl -e 'print "$_\n" for (glob ("*.*"))'

    Update2: And lets add the test fot text files:

    perl -e 'for (glob ("*.*")){print "$_\n" if (-T $_);}'
      For portability, you should get out of the habit of thinking of "*.*" as meaning "all entries in a directory." Just use "*" instead.

      On Un*x varieties including Linux and MacOS X, the period is just another character which might be in a filename. On those platforms, "*.*" finds only those entries that just happen to include at least one period.

      Windows thankfully expects "*" to mean "*.*", so using a single star parameter to glob() is portable on Windows and Un*x varieties both.

      my @subdirectories = grep { not /^\.\.?$/ } grep { -d } glob("*");
      my @files = grep { -f } glob("*");
      There is also a -T check which sniffs the head of a file for anything that doesn't smell like text, but I tend not to trust that kind of contents-check. It's not sufficiently clear if it would say true or false for a few UTF-8 or Latin high-bit characters, which I would still call a "text" file.

      --
      [ e d @ h a l l e y . c c ]

        Funny how you and Argel are slicing the Camel's hair over glob and file systems :-)

        I would say, for portablitiy "get out of the bad habit of using glob" to get a list of files, since glob - what do the docs say?

        In list context, returns a (possibly empty) list of filename expansions on the value of EXPR such as the standard Unix shell /bin/csh would do. In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted.

        There. That dratted csh - glob clearly has a UNIX bias. To know what glob really does, you have to know how the filename expansion of csh works - it uses the shell's wildcard syntax to filter filenames, not perl regular expressions. That's enough reason for me to almost never use glob.

        So - for sake of portability use opendir and readdir.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        Except *.* is not portable either as it does not match UNIX hidden files -- files and directories that begin with a dot. In shells I usually use '.??*' to hit those (where the '??' is a kludge to make sure I avoid '.' and '..' -- the current and parent directory).
          A reply falls below the community's threshold of quality. You may see it by logging in.
        Now that I think about it even on Windows files are not required to have extensions. Some examples are %SystemRoot%\system32\drivers\etc\hosts and the registry hive files.
Re: Read a list of files into an array
by Zaxo (Archbishop) on Jun 22, 2007 at 15:24 UTC

    Or, even more compact way to use glob,

    my $dir = "/path/to"; # or however you initialize my @array = <$dir/*.txt>;
    to get files with the .txt extension. If you want to consider all files for more accuracy, use -f and File::Type to filter <$dir/*>.

    After Compline,
    Zaxo

Re: Read a list of files into an array
by holli (Abbot) on Jun 23, 2007 at 01:04 UTC
    As I have already mentioned here, you could use my upcoming FileSystemObjects-module. If you want to test it, the code for your task would look like
    use FileSystemObjects::Directory; my $d = FileSystemObjects::Directory->new( '/root/dir' ); my @f = $d->files( -mask => "*.txt" );


    holli, /regexed monk/
Re: Read a list of files into an array
by cengineer (Pilgrim) on Jun 22, 2007 at 15:43 UTC
    This sub returns an array ref. You could also opt not to use the sub to access the array directly, instead.
    #!/usr/bin/perl use strict; use warnings; my $somedirectory = "/root/dir/"; my $files = dirlist($someDirectory); foreach my $fileInDirectory (@$files) { dosomething($fileInDirectory); } sub dirlist { my $dir = shift; my @filelist; opendir(DIR, $dir) or die "can't opendir $dir: $!"; while (defined(my $file = readdir(DIR))) { # Skip "." and ".." next if ($file =~ /^\.\.?$/); push(@filelist, $file); } closedir(DIR); return \@filelist; }
Re: Read a list of files into an array
by regexes (Hermit) on Jun 26, 2007 at 11:00 UTC
    Hello,

    If all you want are the text files in a directory....
    how about...

    #!/usr/bin/perl $dir = "/root/dir"; opendir(DIR, $dir) or die "Can't open $dir: $!"; my @files = grep { -T $_ } readdir DIR;

    regexes


    -------------------------
    Nothing in the world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with talent. Genius will not; unrewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence and determination are omnipotent. The slogan "press on" has solved and always will solve the problems of the human race.
    -- Calvin Coolidge, 30th President of the USA.