Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

A Tribute To The Monks Of Wisdom

by koolgirl (Hermit)
on Nov 16, 2008 at 01:41 UTC ( #723870=snippet: print w/replies, xml ) Need Help??
Description:

May I have a drum roll please!

Ok, Monks, I have spent quite a bit of time contemplating whether or not this write-up would be a complete waste of time due to it's insignificance, and whether or not it might even warrant some serious XP loss on my part (though I prayed that it wouldn't *big pouty eyes*). However, I'm doing it anyways, so here goes....

This is a tiny snippet of code, an excersise which teaches basic file manipulation, which is my current venture into the world of Perl. It means nothing, I'm sure, to the code catacombs per se, however, it's significance lies in it's construction. I wrote this in about 45 minutes, encountered several problems, researched them, de-bugged my code, got it working, and even used, at least to a point, a less verbose approach than usual, and I did it all by myself. It is the very first time in several months of hard core studying, that I have accomplished this feat. To be blunt, I just couldn't be more proud of myself...I even did a dance, a 5 minute long dance mind you, after seeing the beautiful output.

Now, before you hit the -- vote while thinking to yourself "I can't believe this absurdity...I could've written that in my sleep and never even needed to de-bug a thing", please allow me to quickly end this monstrosity by explaining why I went ahead with it.

There are a countless number of you, who have dedicated your precious time to answering my many questions over the last few months, all of them revolving around my inability to de-bug my own code without asking another Monk to hold my hand. I wanted to show all of you who were nice enough to help, that your effort was not in vain...ya'll taught me how to de-bug my code. This is a testament to every monk that has ever answered a SoPW question, just to watch that same monk who asked, completely ignore it and continue to ask about it over and over again. I know the experts on here get frustrated with us newbies for such things. So, I wanted to give tangible proof, that the Perl Monks are fantastic teachers and should be praised for it.

So, I hereby dedicate this to every Monk on here, that has ever taken the time to answer a newbie question, in an effort to further a fellow Monk's knowledge. Monks it is truly a privilege and an honor to be a recipient of your guidance!

UPDATE: Fixed the typo and forgotten close. Thanks hossman :D

UPDATE:

Yes, I do realize that the file tests could have been performed without opening them, however, I didn't understand how to open files from the @ARGV, as it was my first time calling a program with file names behind it on the command line, so, I went ahead and researched it and incorporated it into my program, just to give myself the experience.


#!usr/bin/perl

use strict;

my $i = 0;

# This is a program which reads in a list of file names from the comma
+nd 
# line and prints which files are readable, writable and/or executable
+,
# and whether each file exists.

 while ($i < scalar(@ARGV)) {
    open(MYFILE, $ARGV[$i]) or die("Error: cannot open file '$ARGV[$i]
+'\n");

     print "$ARGV[$i] is readable!\n" if -r MYFILE;
    print "$ARGV[$i] is writable!\n" if -w MYFILE;
    print "$ARGV[$i] is executable!\n" if -x MYFILE;
    print "$ARGV[$i] exists!\n" if -e MYFILE;
    $i++;

 } # end while

close(MYFILE);

Replies are listed 'Best First'.
Re: A Tribute To The Monks Of Wisdom
by graff (Chancellor) on Nov 16, 2008 at 05:32 UTC
    To amplify a bit on what hossman said, it's better to use the so-called "-X" operators on file names, before you open the files, because you usually want to know if they exist, are writable, etc, before trying to open them. Of course, if the path/filename doesn't exist, there's no point trying to get more information about it.

    And it's also worthwhile to know that every time you use any one of the -X operators on a given file, it fetches all the properties for the file (because that's how the underlying system library function works), and it keeps them in a cache, so if you use another -X function on the same file as the previous -X function, you can use "_" (underscore) instead of the file name or file handle, to use the cached info instead of reading it from disk again.

    Plus, I like having things structured for loops, and I hate having to repeat things in my perl code when I shouldn't need to... even if it means using "eval" so that I can loop over the tests:

    #!/usr/bin/perl use strict; use warnings; my %test = ( '-f' => 'a data file', '-d' => 'a directory', '-r' => 'readable', '-w' => 'writable', '-x' => 'executable', ); die "Usage: $0 [path/]file.name ...\n" unless @ARGV; for my $file ( @ARGV ) { my $report = "$file does not exist\n"; if ( -e $file ) { $report = "$file exists and is:\n"; for my $t ( sort keys %test ) { $report .= " ... $test{$t}\n" if ( eval "$t _" ); } } print "$report\n"; }
      Liked your code (++), but wanted to avoid "eval" - this works :
      #!/usr/bin/perl use strict; use warnings; my %test2 = ( 'a data file' => sub {-f _}, 'a directory' => sub {-d _}, 'readable' => sub {-r _}, 'writable' => sub {-w _}, 'executable' => sub {-x _}, ); die "Usage: $0 [path/]file.name ...\n" unless @ARGV; for my $file ( @ARGV ) { my $report = "$file does not exist\n"; if ( -e $file ) { $report = "$file exists and is:\n"; for my $t ( sort keys %test2 ) { $report .= " ... $t\n" if $test2{$t}->(); } } print "$report\n"; }

           Have you been high today? I see the nuns are gay! My brother yelled to me...I love you inside Ed - Benny Lava, by Buffalax

Re: A Tribute To The Monks Of Wisdom
by hossman (Prior) on Nov 16, 2008 at 03:16 UTC
    So, I hereby dedicate this to every Monk on here, that has ever taken the time to answer a newbie question, in an effort to further a fellow Monk's knowledge.

    In the spirit of furthering a fellow Monk's knowledge with constructive criticism...

    • It's a good idea to get into the habbit of writing "close" anytime you write "open" ... perl will close any open filehandles for you when your script ends, but even in really short scripts you could conceivable run out of file handles if you use a lot of them (or if your code gets refactored into a longer running program).
    • if you declare a counter (ie: $i) just for hte purposes of looping over an array, consider foreach instead. This...
      foreach my $filename (@ARGV) { open(MYFILE, $filename) or die("Error: cannot open file '$filename'\n"); print "$filename is readable!\n" if -r MYFILE; print "$filename is writable!\n" if -w MYFILE; print "$filename is executable!\n" if -x MYFILE; print "$filename exists!\n" if -e MYFILE; }
      ...is a little bit easier to read (to me) then what you've got right now, and a little less error prone to off by one errors and/or typos (hint: you're using $ARGV[0] in a place where you probably ment to use $ARGV[$i]
    • the file test operators (-r, -x, etc...) can take a filename as an expression, so you don't *have* to open the files first -- in fact if the file doesn't exist, or isn't readable, you won't be able to open it, so some of those test are redundant. :)
Re: A Tribute To The Monks Of Wisdom
by Lawliet (Curate) on Nov 16, 2008 at 03:31 UTC
    #!usr/bin/perl use strict; use warnings; # Oh, hi, you forgot me!

    *ahem*

    I'm so adjective, I verb nouns!

    chomp; # nom nom nom

      #!usr/bin/perl use strict; use warnings; # Oh, hi, this module not available on my windows box

      *Ahhhem*

      ;)

        Does it not come with Perl? :\

        I'm so adjective, I verb nouns!

        chomp; # nom nom nom

Re: A Tribute To The Monks Of Wisdom
by jwkrahn (Monsignor) on Nov 16, 2008 at 23:24 UTC

    You could use the fact that <> opens the files for you:

    #!/usr/bin/perl use warnings; use strict; # This is a program which reads in a list of file names from the comma +nd # line and prints which files are readable, writable and/or executable +, # and whether each file exists. while ( <> ) { print "$ARGV is readable!\n" if -r ARGV; print "$ARGV is writable!\n" if -w ARGV; print "$ARGV is executable!\n" if -x ARGV; print "$ARGV exists!\n" if -e ARGV; close ARGV; } # end while
      Wow, the diamond operator opens the files? Is this only true for @ARGV, or can you also open other files without "open"? Is this something sort of like not declaring your variables, in that just because Perl allows it, doesn't mean it's good form, or is it something commonly done when using @ARGV?

        The diamond always works on the files in @ARGV. It also provides another level of magic, if @ARGV is empty, it reads STDIN. This is a very common idiom for writing filter programs.

        Another useful trick is to realize that @ARGV starts out with the command line parameters, but it is just a variable. You can change it. (For example, remove some flags or commands and then process the rest, or use the parameters to construct a list of filenames that replaces @ARGV before processing.

        The last trick is not one to be used lightly, because it's likely to confuse some people. But, sometimes it is exactly the tool you need.

        G. Wade

        I personally believe that the "only" risk associated with it is that you can pass arbitrary code to be executed, so it all depends on whom do you plan to make your script available to and to security settings. Thus

        perl -pe ''

        can be considered as an equivalent to cat(1) (well, except for the bazillion cmd line switches, of course!) but if you do

        perl -pe '' "rm -rfv $HOME |"

        then you're on your own. However FWIW it just boils down to doing

        rm -rfv $HOME

        in the first place. You "just" have to make sure others are not allowed to do the same or similar things, if you use the diamond operator: of course the issue has nothing to do with Perl anymore, but with your system's administration instead.

        --
        If you can't understand the incipit, then please check the IPB Campaign.
Re: A Tribute To The Monks Of Wisdom
by blazar (Canon) on Nov 21, 2008 at 10:50 UTC

    May I have a drum roll please!

    Ok, Monks, I have spent quite a bit of time contemplating whether or not this write-up would be a complete waste of time due to it's insignificance, and whether or not it might even warrant some serious XP loss on my part (though I prayed that it wouldn't *big pouty eyes*). However, I'm doing it anyways, so here goes....

    I personally believe that I can understand your concerns. In fact if I were you I would keep such a snippet for myself: there's been a recent, instructive and thorough discussion about how to do to so. In fact snippets posted here should be aimed at providing general help to monks, however simple they may look: and I don't think it qualifies. In this sense I see two major issues with it:

    • it still looks much like a work in progress, despite your enthusiasm that you made it work: just consider how many answers and comments you received; IMHO a snippet should be like a well cleaned up and polished peArl illustrating a general concept;
    • it is not about a "A Tribute To The Monks Of Wisdom" which is completely useless as a title for future reference: that it is your dedication to some helpful people here is mostly irrelevant. (Which is also the reason why I considered it.)

    This is a tiny snippet of code, an excersise which teaches basic file manipulation, which is my current venture into the world of Perl. It means nothing, I'm sure, to the code catacombs per se, however, it's significance lies in it's construction. [...]

    (Additional emphasis from me.)

    Then it would have been perhaps better suited to the Meditations section, or perhaps if you wanted to stress the help received here, then to Perl Monks Discussion.

    --
    If you can't understand the incipit, then please check the IPB Campaign.
Re: A Tribute To The Monks Of Wisdom
by blazar (Canon) on Nov 21, 2008 at 11:56 UTC

    I personally believe that I will also comment on your code. I've given a glance at the other responses thus far, but I'm replying as if I only saw your post: you'll surely notice some repetitions with comments by others, this should help to stress some issues it has, and in particular to show you why it was a bad idea to post it in this section to start with.

    #!usr/bin/perl use strict;

    "Wrong" shebang line (but it won't matter if you're under Windows - not a good reason not to put it right there too: it will help portability!) And missing use warnings; line too.

    # This is a program which reads in a list of file names from the comma +nd # line and prints which files are readable, writable and/or executable +, # and whether each file exists.

    Not terribly compelling, but for a snippet you may have considered using a tiny piece of POD rather than comments.

    while ($i < scalar(@ARGV)) { open(MYFILE, $ARGV[$i]) or die("Error: cannot open file '$ARGV[$i] +'\n");

    Three issues:

    • in [Pp]erl, TMTOWTDI, but there are indeed prefer{red,able} WTDI for some specific and common tasks: please let me tell you that the way you adopt to iterate over @ARGV is the most uselessly byzantine I could think of. Incidentally, Perl DWIM most of the times to help you write clean and terse code: that scalar is redundant there;
    • if you're using the two-args form of open you may well rely on *ARGV's implicit open() instead. But then you use file tests in which case I would avoid opening at all unless you have a good reason to so. However, if you do then all of the remaining "standard" recommendations about open() apply too: in particular those about using the three-args form, and lexical handles. I'm not repeting here why it's good to follow them because it is done ad nauseam on a daily basis;
    • it would also be good to say people why something went wrong, and thus include $! in the error message.
    print "$ARGV[$i] is readable!\n" if -r MYFILE; print "$ARGV[$i] is writable!\n" if -w MYFILE; print "$ARGV[$i] is executable!\n" if -x MYFILE; print "$ARGV[$i] exists!\n" if -e MYFILE; $i++;

    In terms of logic and UI: are you sure about that order? Incidentally, if the file didn't exist, could have you opened for reading?

    } # end while

    If you really needed that, then probably you wanted a language which supports such specifications at the level of the syntax. Or else you'd have a too big a while loop, in which case I'd recommend you to trim it down. All in all I would rewrite your program like

    #!/usr/bin/perl use strict; use warnings; use 5.010; for my $file (@ARGV) { -e $file or next; say "`$file' exists!"; say "`$file' is ", ( $_->[1]() ? "" : "not " ), $_->[0] for [readable => sub () { -r _ }], [writable => sub () { -w _ }], [executable => sub () { -x _ }]; } __END__
    --
    If you can't understand the incipit, then please check the IPB Campaign.
Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (8)
As of 2019-08-23 14:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?