View Full Version : Display a list of folders in a dir
NiteOwl
07-16-2007, 05:24 AM
I need to read a dir and store a list of folders in an array
This is what i have but, the code displays everything.
#!/perl/bin/perl
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";
# A small program to read the contents
# of a directory and print them to screen
@dir_contents;
$dir_to_open="C:/Documents and Settings/James/My Documents/My Website/auto/cgi-bin";
# open file with handle DIR
opendir(DIR,$dir_to_open) || die("Cannot open directory !\n");
# Get contents of directory
@dir_contents= readdir(DIR);
# Close the directory
closedir(DIR);
# Now loop through array and print file names
foreach $file (@dir_contents)
{
if(!(($file eq ".") || ($file eq "..")))
{
print "$file \n";
}
}
Thanks for looking
FishMonger
07-16-2007, 06:21 AM
#!/perl/bin/perl
use strict;
use warnings;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";
warningsToBrowser(1);
# A small program to read the contents
# of a directory and print them to screen
my $dir_to_open = "C:/Documents and Settings/James/My Documents/My Website/auto/cgi-bin";
my @dir_contents = grep -d, <$dir_to_open/*>;
print "Directory: $_<br>\n" for @dir_contents;
KevinADC
07-16-2007, 07:11 AM
A windows specific suggestion:
my $dir = 'C:\\Documents and Settings\\James\\My Documents\\My Website\\auto\\cgi-bin';
@array = qx|dir $dir /B /A:D /O:N|;
print "$_" for @array;
You have to use backslashes because DOS does not recognize forward slashes as directory paths.
/B lists them in bare format (just the name)
/A:D lists only directories (no subdirectories)
/O:N sorts them by name
The above options may vary from one version of windows to the next. You can always type "dir /?" at the DOS prompt to see what your version supports.
FishMonger
07-16-2007, 07:36 AM
You have to use backslashes because DOS does not recognize forward slashes as directory paths.Not quite true, Windows has that limitation, but Perl lets you use either.
C:\>C:\>type dirlist.pl
#!/perl/bin/perl
use strict;
use warnings;
my $dir_to_open = 'C:/Perl/HTML';
my @dir_contents = grep -d, <$dir_to_open/*>;
print "Directory: $_\n" for @dir_contents;
C:\>dirlist.pl
Directory: C:/Perl/HTML/bin
Directory: C:/Perl/HTML/Components
Directory: C:/Perl/HTML/faq
Directory: C:/Perl/HTML/images
Directory: C:/Perl/HTML/lib
Directory: C:/Perl/HTML/PerlEx
Directory: C:/Perl/HTML/site
Directory: C:/Perl/HTML/Windows
Personally, I don't feel the need to spawn a separate process to execute the Windows dir command, when Perl has built-in methods.
KevinADC
07-16-2007, 10:11 AM
I agree with you Fish. I would probably use a pure perl approach too, but sometimes the OS is a good option.
Actually, Windows has always supported forward or back slashes in directory paths. Which is why you can use either in your perl scripts. But DOS does not. The "dir" command is a DOS command, not a Windows command. DOS treats forward slashes as switches for adding arguments/options to DOS commands. A quick test shows DOS does not recognize forward slashes in directory paths:
my $dir = 'C:/Windows';
@array = qx|dir $dir /B /A:D /O:N| or die "$!";
print "$_" for @array;
output:
Invalid switch - INDOWS
Bad file descriptor at script line 2.
NiteOwl
07-16-2007, 07:24 PM
Thanks All.
I forgot to say what OS i would be using.
I test on windows with xampp and run on UNIX
I do get just a blank screen when i run this
FishMonger
07-16-2007, 09:20 PM
What path are you using in $dir_to_open when you run it on the Unix box?
Are there any warnings or error messages in the web server error log; if so, what are they?
Have you manually checked to see if there are any directories in the path you're searching?
FishMonger
07-16-2007, 11:58 PM
I forgot to ask for clarification on a 1 or 2 other points.
Clearly, the Windows dir command won't work on Unix, so which method are you using, the opendir/readdir approach or the grep approach that I showed?
If you're using opendir/readdir, are you using the -d file test to find the directories?
Please post your updated code, so we can see if there are any obvious issues.
nkrgupta
07-17-2007, 06:11 AM
On a different note... if your production environment is Unix, and you want to use Windows for development/testing, then you might as well consider installing Cygwin (http://www.cygwin.com/) on your Windows box, which will give you an almost identical (if not completely identical) simulation of the Unix environment. Moreover, you use the same set of commands, applications and techniques on Cygwin as you don on any *nix box! Its simply awesome.
Naveen
NiteOwl
07-19-2007, 05:21 AM
My original code uses opendir and displays both folders and files. I just want it to show folders, only.
If i uploaded it to the unix server i would change 2 lines and get the same thing.
#!/usr/bin/perl
$dir_to_open="/hsphere/local/home/jamesw/my.com/cgi-bin/";
FishMonger
07-19-2007, 06:24 AM
Using grep as I showed in my first post would be the easiest, but if you want to use opendir/readdir then here's an example.
#!/usr/bin/perl
use warnings;
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
# A small program to read the contents
# of a directory and print them to screen
my $dir_to_open = "/var/www/cgi-bin";
print header();
warningsToBrowser(1);
print start_html(),
h2("Directories found in $dir_to_open");
opendir(DIR, $dir_to_open) || die("Cannot open directory $!");
foreach my $dir_entry ( readdir(DIR) ) {
next if $dir_entry =~ /^\.+$/ or ! -d $dir_entry;
print h3($dir_entry);
}
closedir(DIR);
print end_html();
NiteOwl
07-21-2007, 03:29 AM
Thanks, Exactly what i needed.
:thumbsup:
NiteOwl
07-22-2007, 01:50 AM
I went to use this code, and it failed to display folders that have numeric names, such as, 2007.
I really don't need to Re-write my entire code.
My first example worked fine, but, it displayed both files and folders.
I really just need help defining which to display by altering the code below.
foreach $file (@dir_contents)
{
if(!(($file eq ".") || ($file eq "..")))
{
print "$file \n";
}
}
I need to display just folders. How can i change the above code to do that?
Also..
in another program, I will also need, to display just files inside of a folder.
How can i alter, the code above to do that?
My original code:
#!/perl/bin/perl
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";
# A small program to read the contents
# of a directory and print them to screen
@dir_contents;
$dir_to_open="C:/Documents and Settings/James/My Documents/My Website/auto/cgi-bin/payments";
# open file with handle DIR
opendir(DIR,$dir_to_open) || die("Cannot open directory !\n");
# Get contents of directory
@dir_contents= readdir(DIR);
# Close the directory
closedir(DIR);
# Now loop through array and print file names
foreach $file (@dir_contents)
{
if(!(($file eq ".") || ($file eq "..")))
{
print "$file <br>";
}
}
Thanks for all your help...
FishMonger
07-22-2007, 02:34 AM
Numeric folder names will not prevent the script from finding/displaying them, but I just noticed 2 errors on my part in that last example I gave you.
I think you unknowingly figured out the first one; the foreach loop should be looping over the @dir_conents array instead of readdir(DIR). The second error of mine was that I forgot that readdir does not return the $dir_to_open path, so you'll need to add that back in when you do the file tests.
foreach $file (@dir_contents)
{
if(!(($file eq ".") || ($file eq "..")))
{
next if -f "$dir_to_open/$file"; # this skips over regular files
print "$file <br>";
}
}
foreach $file (@dir_contents)
{
if(!(($file eq ".") || ($file eq "..")))
{
next if -d "$dir_to_open/$file"; # this skips over directories
print "$file <br>";
}
}
http://perldoc.perl.org/functions/-X.html
FishMonger
07-22-2007, 02:44 AM
If you want, you can do the file test in the if contiional.
# get files
if(!(($file eq ".") || ($file eq "..")) and -f "$dir_to_open/$file")
{
print "$file <br>";
}
# get directories
if(!(($file eq ".") || ($file eq "..")) and -d "$dir_to_open/$file")
{
print "$file <br>";
}
or
print "$file <br>" if(!(($file eq ".") || ($file eq "..")) and -f "$dir_to_open/$file");
print "$file <br>" if(!(($file eq ".") || ($file eq "..")) and -d "$dir_to_open/$file");
NiteOwl
07-22-2007, 03:14 AM
Both worked perfectly, Thank you.
I had a a hard time searching for the way to do this.
I always come here next.
And, like always, Problem Solved.
Thanks again....
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.