Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

How do I read all the file names of a directory into an array?

by Ri-Del (Friar)
on Dec 10, 2000 at 12:59 UTC ( #45928=perlquestion: print w/replies, xml ) Need Help??

Ri-Del has asked for the wisdom of the Perl Monks concerning the following question: (files)

I would like to read the names of all the files in a directory of mine into an array so that I can convert each file name into a link to that file. Currently I am doing this in the following manner. I read the "dir.dat" file with the following command, "ls > dir.dat." I should like rather to get the current directory's files from within the script rather than having to do that command everytime I want to regenerate the html. How might I do this?
#!/usr/local/bin/perl use strict; @filename; $i = 0; $total; open(INFILE,"dir.dat"); while($filename[$i] = <INFILE>){ chop($filename[$i]); $filename[$i] =~ s/\*//g; $i++; $total++; } $error = open(OUTFILE,"> dict.html"); if(!$error){ print("ERROR\n"); exit(0); } print(OUTFILE "<HTML>\n <HEAD>\n </HEAD>\n <BODY TEXT=#00ff00 LINK=# +00ff00 VLINK=#00ff00 BGCOLOR=#000000 alink=00FF00>\n"); for($i=0;$i<=$total;$i++){ print(OUTFILE "<A HREF=\"$filename[$i]\">$filename[$i]</A><BR>\n"); } print(OUTFILE "</BODY>\n</HTML>\n"); close(OUTFILE);

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I read all the file names of a directory into an array?
by mirod (Canon) on Dec 10, 2000 at 14:31 UTC

    Use the directory functions: opendir, closedir and readdir.

    opendir DIR, $dir or die "cannot open dir $dir: $!"; my @file= readdir DIR; closedir DIR;

    This will neatly put the list of file names in the @file array (with no \n at the end of each file name).

    There is a couple of other things you can improve in your code BTW:

    • use Perl style loops over arrays:
      foreach my $file (@file) { print "$file\n"; }
      this is much simpler than using C-style for( $i=0;...) loops, you don't have to use $i and $total any more (BTW $#filenames would give you the last index in the @filenames array, you don't have to use $total)
    • do not use chop but chomp instead, it's safer as it will not remove the last character of a string if it is not a newline.

    Finally I have no idea why $filename$i =~ s/\*//g; is there? Is there a chance you that you might find a '*' in filenames?

      Wow! Everyone thank you ever so much for your help, I've been learning so much! Yes, there is a chance I will find a '*' in the filenames. For some reason when I am connected to my department's server (running RedHat 7.0) and I 'ls' a directory some of the files (not all of them) have a '*' after their name. I'm not quite sure why, but I knew I needed to get rid of them to craft the link correctly for the webpage.
        That's a perfect example of why you should be reading the directory listing from within Perl (i.e. the opendir/readdir solution), rather than using a non-portable external command.

        On the department's server, `ls` is aliased to `ls -F`. The -F option causes ls to add * to executables, / to directories, and @ to symbolic links. Useful when looking at a directory listing from the command prompt; not useful when getting a list of filenames within Perl.

        I believe that the reason there are *'s after some files is because ls is aliased to ls -F, which will add a * to the end of files that are executeable. It will also add some other characters onto files that are directories, symlinks, etc.... You won't run into that using readdir though. Hope this helps!

        - Brad
Re: How do I read all the file names of a directory into an array?
by mrmick (Curate) on Dec 10, 2000 at 20:14 UTC
    You want to open the directory (handle) and read all filenames into an array using readdir. This will read all files (including . and .. into the array). From here you can use a foreach loop to iterate throught he array and do what you want:
    my $directory = 'c:\windows'; opendir(DIR,$directory); my @files = readdir(DIR); closedir(DIR); foreach(@files){ print $_,"\n"; }
    I hope this gets you going in the right direction...

    Mick

Re: How do I read all the file names of a directory into an array?
by kilinrax (Deacon) on Dec 10, 2000 at 17:02 UTC
    Use opendir, readdir and closedir.
    Assuming you don't want '.' or '..' to appear in the list of filenames, the following is probably what you are looking for:
    opendir DIR, "directory/"; my @files = grep { $_ ne '.' && $_ ne '..' } readdir DIR; closedir DIR;
Re: How do I read all the file names of a directory into an array?
by reyjrar (Hermit) on Dec 12, 2000 at 22:20 UTC
    lucky for you.. perl has built in functions for this:
    my $directory="/home/myuser/mp3s"; opendir(DIR, $directory) or die "couldn't open $directory: $!\n"; my @files = readdir DIR; closedir DIR;
    you can also use readdir in scalar context to just return the next item in the directory.
    -brad..
Re: How do I read all the file names of a directory into an array?
by gt8073a (Hermit) on Dec 12, 2000 at 01:24 UTC
    I would like to read the names of all the files in a directory of mine into an array so that I can convert each file name into a link to that file.

    very simply, use opendir, readdir, and closedir

    my $dir = '/'; ## rem trailing slash my $body; ## our file list my $saveFile = '/dev/null'; ## file to save links opendir( MYDIR, $dir ) or die 'opendir'; $body = join( "\n", ## make it legible map { '<a href="$_">$_</a><br>' } ## format each file sort { $a cmp $b } ## sort them grep { ! /^\./ } ## no .name files grep { -T "$dir$_ } ## only text files readdir MYDIR ); closedir MYDIR; ## build your link page ## using $body open( FILE, $saveFile ) or die 'open'; print FILE <<EOF; <HTML> <HEAD> <TITLE>My Files</TITLE> <BODY> $body </BODY> </HTML> EOF close FILE;

    see also join, grep, map, and sort
    ( along with Schwartzian Transform and file test operators )

    --jj--

      A tip about grep and map: using two in a row is almost always unnecessary. For example, the grep {} grep {} in the above code can be made into a single grep {} with the and operator.
      map { qq{<a href="$_">$_</a><br>} } ## format each file sort ## sort them grep { !/^\./ and -T "$dir$_" } ## no .name files, text fil +es only readdir MYDIR
Re: How do I read all the file names of a directory into an array?
by I0 (Priest) on Dec 10, 2000 at 15:03 UTC
    @filename=grep !/^\.\.?$/, <*>;
Re: How do I read all the file names of a directory into an array?
by epoptai (Curate) on Dec 11, 2000 at 08:07 UTC
    opendir DIR, "." or die "uhh: $!"; @files = readdir DIR; closedir DIR;
Re: How do I read all the file names of a directory into an array?
by feloniousMonk (Pilgrim) on Apr 24, 2001 at 19:42 UTC
    You can alse use DirHandle.

    Like so:
    my $dhandle = new DirHandle "/directory/to/foo"; #or my $dhandle = new DirHandle "."; for #current directory, if you like if (defined($dhandle)){ while (defined($_ = $dhandle->read)){ push @filename_array,$_; } } undef($dhandle);

    This is pretty much from the DirHandle manpage
    also, so it's well documented. And I like it.

    --
    -felonious
Re: How do I read all the file names of a directory into an array?
by eg (Friar) on Dec 10, 2000 at 13:37 UTC

    Use backticks (`) to execute a shell command and capture its output (see the perlop manpage):

    my @filename = split("\n", `ls`); my $total = scalar(@filename);

    This would replace everything after the line "use strict;" and before "$error = ...".

    Note you can also replace your for-loop with a foreach which would mean you wouldn't need $total any longer. See perlsyn.

Re: How do I read all the file names of a directory into an array?
by epoptai (Curate) on Dec 11, 2000 at 08:12 UTC
    opendir DIR, "." or die "uhh: $!"; @files = readdir DIR; closedir DIR;
Re: How do I read all the file names of a directory into an array?
by peppiv (Curate) on Dec 14, 2001 at 19:15 UTC
    Working off of the array of file names, this is how I created a link to the file.
    #!/usr/bin/perl print "Content-type: text/html\n\n"; opendir(INFILE, "dir.dat") || die ("Unable to open directory"); #this line gets rid of . and ..<br> @files = grep !/^\./, readdir(INFILE); closedir(INFILE); foreach $file (sort @files) { print ("<font size=\"2\"face=\"arial\"><a href=/owner/$file>$ +file</a></font>\n<br>"); }

    peppiv

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (4)
As of 2021-04-21 06:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?