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

I have a DIR in the cgi-bin called start
The DIR holds several files
12345.data
12346.data
12347.data
I would like to print the contents of this DIR
As a list
12345.data
12346.data
12347.data
I don’t need to see inside the files
Just print a list of the file names.
I have tried
opendir DIR, "start" or die "Can't open: $!"; my @files = grep { /\.txt\z/ } readdir DIR; closedir DIR; print "Content-type: text/html\n\n"; foreach my $file (@files) { open FILE, $file or die "Can't open file: $!"; while (<FILE>) { print $_; } }

However it prints nothing
Where am I going wrong I think it cant see my DIR.
I have tried various way to tell it where the DIR is
Like so
opendir DIR, "start" or die "Can't open: $!";
opendir DIR, "start/" or die "Can't open: $!";
opendir DIR, "/start" or die "Can't open: $!";
opendir DIR, "C:/Apache2/cgi-bin/start" or die "Can't open: $!";
opendir DIR, "http://localhost/cgi-bin/start" or die "Can't open: $!";
But nope it still cant see my DIR
Going mad with this ..Nasa.

Replies are listed 'Best First'.
Re: print directory contents
by liverpole (Monsignor) on Dec 10, 2006 at 01:48 UTC
    Hi nasa,

    It looks to be because you're not constructing the full path of the file.

    After you read the list, make sure that you prepend the directory name to each file before trying to open it:

    my $dir = "start"; foreach my $file (@files) { my $path = "$dir/$file"; open FILE, $path or die "Can't open file '$path': $!"; while (<FILE>) { print $_; } }

    Update:  Now that I re-read your question, I realize I missed that it's the directory you're having trouble with (although my comments above will still apply, once you've read the directory successfully, since you are, in fact, trying to open each file, and that will require the full pathname).

    If you're doing this through http, try having the script print the working directory (after, of course, printing the Content-type header):

    use Cwd; my $thisdir = getcwd; print "Content-type: text/html\n\n"; print "Current directory = $thisdir\n";

    You should be able to figure out how to traverse into cgi-bin relative to that.  One guess is that it might be simply /cgi-bin.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: print directory contents
by ikegami (Patriarch) on Dec 10, 2006 at 01:48 UTC
    Your current directory is not always the same as the directory in which your script resides. Try specifiying the absolute path instead of just start, or try
    use File::Spec::Functions qw( catdir rel2abs ); use File::Basename qw( basename ); my $start_dir = catdir(basename(rel2abs($0)), 'start'); open(DIR, $start_dir) ...

    Also, readdir doesn't return a full path.

    use File::Spec::Functions qw( catfile ); foreach (@files) { my $file = catfile($start_dir, $_); ... }
Re: print directory contents
by madbombX (Hermit) on Dec 10, 2006 at 02:44 UTC
    You may want to look at File::Find to get the list of files. Something similar to the following code will find a list of all the .txt files in the start directory (Note: You can always modify the regex if need be):
    use strict; use warnings; use File::Find; my @files; my $dir = "C:/Apache2/cgi-bin/start"; find( sub { push @files, $File::Find::name if -f && /.+\.txt/ }, $dir +); print "Content-type: text/html\n\n"; foreach my $file (@files) { open FILE, '<', $file # This is assuming you only want to read th +e file or die("Can't open file ($file): $!"); while (<FILE>) { print $_; } close (FILE) or die("File close error ($file): $!"); }
Re: print directory contents
by Not_a_Number (Prior) on Dec 10, 2006 at 08:08 UTC

    Sometimes the silliest things drive me mad, too. Look at your filenames again, and then look at your code again. The filenames you want to print out have a '.data' extension, but you're grepping for files that end in '.txt'.