Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

list dir contents, w/o some stuff

by einerwitzen (Sexton)
on Jan 14, 2002 at 11:58 UTC ( [id://138537]=perlquestion: print w/replies, xml ) Need Help??

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

I have the following bad newbie code, that i know doesn't work, but i'm hoping someone will realize what i'm tryin to pull off. How can I make a list of things not to show when the contents are listed (one elements on the list is the name of the script running this, loaded 'dynamically')?

Wondering if anyone can fix this?

#!/usr/bin/perl print "Content-type: text/html\n\n"; opendir(DIR,"./") || die print "Couldn't open directory"; @files = readdir(DIR); closedir(DIR); $filename = __FILE__; @nowshow = (".", "..", $filename); foreach $f (@files) { unless ( ($f eq @noshow) ) { print "$f <br>"; } }

Replies are listed 'Best First'.
Re: list dir contents, w/o some stuff
by Chmrr (Vicar) on Jan 14, 2002 at 12:18 UTC

    First off, use strict warnings and diagnostics or die even for code of this size. You had a typo with @nowshow that strict would have picked up. One might also want to consider use CGI or die; if this project involves handling form input. If this is all that it is, though, you might be able to escape without using it.

    All that aside, I'd probably do something like:

    #!/usr/bin/perl -w use strict; print "Content-type: text/html\n\n"; opendir(DIR,"./") or die "Couldn't open directory"; my @files = readdir(DIR); closedir(DIR); my @noshow = (".", "..", __FILE__); foreach my $f (@files) { print "$f<br>\n" unless grep {$f eq $_} @noshow; }

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

(crazyinsomniac) Re: list dir contents, w/o some stuff
by crazyinsomniac (Prior) on Jan 14, 2002 at 12:24 UTC
    That is interesting syntaxt there ... what sources are you learning perl from?

    What you need to read is perlop, look for the "eq" operator, and then check out perlfunc:scalar (cause that be the "context" you're putting @files in), perldata and of course perlsyn.

    I mentioned all of the above just cause I like pod very much, and you should read them in either case.

    Also, see perlfunc:die, cause die print "blah" is not what you want. die writes to STDERR, print writes to STDOUT, so you'd get 'blah' on STDOUT (the browser), and 1 in the error log. you either want to "die", or print "blah" and die;

    Remember that foreach you got for @files, you need one for @noshow (btw - like perlsyn says, for is an alias for foreach ;D). It might not be apparent, but you can also use perlfunc:grep to do what you want. Monks usually use it like so (untested, but should work):

    #!/usr/bin/perl -w use strict; # always use strict, or die opendir(DIR,'./') or die "couldn't open directory"; my $noshow = join '|', map { quotemeta } ('.','..',__FILE__); my @files = grep !/$noshow/, readdir(DIR); print "$_<BR>" for @files;

    PS - You, and every monk there is, should also read How to RTFM. It is invaluable.

    update: hey, everybody decided to reply to this, and I'm last, whohooo.
    update: One of the most inportant things to understand about perl, besides references, is "context", and japhy's article sums it up pretty nicely. Also, you might wanna check out perlfunc:map and perlfunc:quotemeta. I assume you are familiar with $_;

     
    ______crazyinsomniac_____________________________
    Of all the things I've lost, I miss my mind the most.
    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Re: list dir contents, w/o some stuff
by Rich36 (Chaplain) on Jan 14, 2002 at 12:21 UTC

    You're very close on this one...
    One thing you will see a lot around here - use strict and the -w flag.
    One of the things that using the warning flag and the strict pragma would have caught is that you have two different names for the array that you use to contain the files you don't want to list - @nowshow and @noshow. Using strict and the -w flag can save a lot of heartache and headaches in finding problems in your code. Also, if this is a CGI script, you want to look into the -T flag. Take a look at perlsec for more information.

    The other problem is with the unless statement. $f eq @noshow won't work. It won't tell you if $f is equal to a value in @noshow. What you need to do is use the grep function. This pulls out information from a list based on the criteria that you set. In the code below, it searches for $f in the list of filenames not to display. If it finds it, it won't print it out.

    Finally, another recommendation - use CGI or die. The module CGI.pm provides many, many built in functions for creating CGI scripts. It's invaluable for creating CGI programs.

    #!/usr/bin/perl -w print "Content-type: text/html\n\n"; opendir(DIR,"./") || die print "Couldn't open directory"; my @files = readdir(DIR); closedir(DIR); my $filename = __FILE__; my @noshow = (".", "..", $filename); foreach $f (@files) { unless (grep /$f/, @noshow) # look for $f in @noshow { print "$f <br>\n"; } }

    Rich36
    There's more than one way to screw it up...

Re: list dir contents, w/o some stuff
by jlongino (Parson) on Jan 14, 2002 at 12:33 UTC
    In the spirit of TIMTOWTDI, this example uses hash lookup which may be a bit more efficient than grep (provided that %noshow is small and @files is medium to large. The larger, the better.):
    use strict; use File::Basename qw( basename ); print "Content-type: text/html\n\n"; opendir(DIR,"./") or die "Couldn't open directory"; my @files = readdir(DIR); closedir(DIR); my %noshow = ("." => 1, ".." => 1, basename($0) => 1 ); foreach my $f (@files) { print "$f<br>\n" unless exists $noshow{$f}; }

    --Jim

    Update 1: I used the example by Chmrr as a starting point.
    Update 2: Added File::Basename support. Thanks tye.

(tye)Re: list dir contents, w/o some stuff
by tye (Sage) on Jan 14, 2002 at 19:57 UTC

    I did a quick scan of the current batch of responses and I didn't see anyone mention that __FILE__ (and $0, for that matter) can often contain the full path of the script rather than just the basename. This would prevent all of the fine solutions presented so far from correctly filtering out the script name.

    You can fix this via:

    use File::Basename qw( basename ); my @noshow= ( ".", "..", basename(__FILE__) );

    Also, you appear to be listing all of the files in the directory where the script is located which hints that you might be allowing people to upload files into this directory. For security reasons with CGI scripts, you really don't want anyone to have write access to directories or files that are near the CGI scripts. Your CGI scripts usually end up under a directory named something like cgi-bin. In any case, your CGI scripts will be stored in directories that the web server is configured to run scripts from. And you really don't want to allow people to upload files or write to files in a directory where the web server runs scripts from. A cracker could upload a nasty script and then tell your web server to run it!

    If you need to upload files, do it to a special directory that is not under cgi-bin. If possible, put the directory someplace that the web server isn't even configured to look at, for example, some place not under public_html or webroot (the exact name of the root directory for your chunk of the web will vary based on server configuration).

            - tye (but my friends call me "Tye")
Re: list dir contents, w/o some stuff
by Chrisf (Friar) on Jan 14, 2002 at 12:24 UTC
    Also bad newbie code, but should do it for you ;-)

    use strict; my (@files, @printThis); my $contentDir = './'; opendir(DIR, "$contentDir") || die "Can't open dir: $!"; @files = readdir(DIR); closedir(DIR); foreach (@files) { if ($_ !~ /^\.+/) { push @printThis, $_; } } # then print out your content

    Update: Move along, nothing to see here ;-)

Re: list dir contents, w/o some stuff
by einerwitzen (Sexton) on Jan 14, 2002 at 13:52 UTC
    thanx Rich36, for now yours seems the easiest for me to understand :)

    just for reference, the die print "blah"; I was just using for debugging when viewed from the browser, any better way to do that, anyone?

    thanx all!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2025-06-14 22:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.