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);
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";
}
| [reply] [d/l] |
|
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
| [reply] [d/l] |
Re: A Tribute To The Monks Of Wisdom
by hossman (Prior) on Nov 16, 2008 at 03:16 UTC
|
| [reply] [d/l] [select] |
Re: A Tribute To The Monks Of Wisdom
by Lawliet (Curate) on Nov 16, 2008 at 03:31 UTC
|
| [reply] [d/l] |
|
#!usr/bin/perl
use strict;
use warnings; # Oh, hi, this module not available on my windows box
*Ahhhem*
;) | [reply] [d/l] |
|
| [reply] |
|
|
|
|
|
Re: A Tribute To The Monks Of Wisdom
by jwkrahn (Abbot) on Nov 16, 2008 at 23:24 UTC
|
#!/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
| [reply] [d/l] [select] |
|
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?
| [reply] |
|
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.
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
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.
| [reply] [d/l] |
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__
| [reply] [d/l] [select] |
|
|