On Tue, May 07, 2013 at 12:00:10PM -0600, Sherman Willden wrote:
> Lines written to a file are not contiguous.

OK. Let's take a look then...

(Note that your mail client seems tos have wrapped the code...
I'm going to fix that in my quotes so it's readable)

> #!/usr/bin/perl
> 
> use v5.16.3;
> # use v5.14.2;
> use File::Basename;
> use File::Path;
> 
> my $base_directory = 
> "/home/sherman/perl_documentation/programming_perl_4_examples/programming_perl_examples/program_listings";
> my $basename_directory = basename($base_directory) || die "Unable to 
> determine the basename: $!\n";

You should be cautious using the || operator for this purpose.
What you're really saying is:

my $basename_directory = (
        basename($base_directory) ||
        die("Unable to determine the basename: $!")
        );

The 'or' operator exists for this purpose. It has extremely low
precedence so that the assignment operator ('=') is evaluated
first:

my $basename_directory = basename($base_directory) or
        die "Unable to determine the basename: $!";

Which means:

(my $basename_directory = basename($base_directory)) or
        die("Unable to determine the basename: $!");

Since 'die' raises an exception it doesn't really matter to Perl
because the assignment will never be evaluated, and even if it
were the value would never be used. It might matter though if the
right-hand expression isn't die so keep it in mind. The 'or'
operator expresses your intent more accurately in either case.

One last thing: When your program prints the exception it will
add context information and add a newline automatically. So the
newline that you're adding is probably redundant. :)

> my $write_directory = 
> "/home/sherman/perl_documentation/programming_perl_4_examples/consolidated_perl4_examples";
> if ( not -e "$write_directory" ) {

The use of 'not' here is similar to '||' above, except reversed.
It has very low precedence, whereas '!' has higher precedence.
Again, it doesn't matter here, but it's something to keep in
mind. They aren't exactly synonymous. Optionally you could use
'unless' instead of 'if', and eliminate the explicit
not-operation entirely, but it's just semantics: some like it and
some don't.

>     mkdir("$write_directory") || die "Unable to create $write_directory: 
> $!\n";
> }
> 
> chdir($base_directory) || die "Unable to change directory to 
> $basename_directory: $!\n";
> 
> opendir(PERLDIR, ".") or die "Unable to open $basename_directory: $!\n";

You generally should prefer lexical file and dir handles instead
of barewords:

opendir(my $dh, '.') or
        die "Unable to open $basename_directory: $!";

> my @docdirs = grep { $_ ne '.' and $_ ne '..' } readdir PERLDIR;
> closedir(PERLDIR) || die "Unable to close $basename_directory:$!\n";
> foreach my $directory ( @docdirs ) {
>     chdir("$base_directory/$directory") || die "Unable to change directory to 
> $directory: $!\n";

Changing directories is fine, but in the case where you want to
write to many files in various places it probably makes better
sense to remain where ever you start (or move somewhere specific
for precautionary reasons, depending on the program). I would
argue that the changing of directories adds needless
complexities.

>     my $write_file = "$write_directory/$directory";
>     opendir(EXAMPLES, ".") or die "Unable to open $directory: $!\n";
>     my @docfiles = grep {$_ ne '.' and $_ ne '..'} readdir EXAMPLES;
>     closedir(EXAMPLES) || die "Unable to close $directory: $!\n";
>     foreach my $file ( @docfiles ) {
>         my ( $write, $read );

$read and $write do not appear to be used. Even if they were,
it's generally preferred to declare them where you first
initialize/use them.

>         open(WRITE, ">>$write_file") || die "Unable to open $write_file: 
> $!\n";

Again, you should prefer lexical file handles. You should also
prefer the 3-argument (or more) open(). It is safer because the
'mode' is a separate parameter.

open my $write_fh, '>>', $write_file) or
        die "Unable to open $write_file: $!";

>         open(READ, $file) || die "Unable to open $file: $!\n";

Again, 3-argument open is preferred. If $file has a specially
crafted name then this might do Something Evil(tm). For a hint,
see what your shell says about:

bash$ touch 'echo rm -i ~'

So make sure to always use the 3-argument open. Even if the
arguments are guaranteed to be safe ("untainted") right now, that
might change.

open my $read_fh, '<', $file or die "Unable to open $file: $!";

>         my $line = readline(READ) || die "Unable to read $file: $!\n";
>         print WRITE "$line\n";

This is where you lose me. Unless I'm missing something you seem
to be only reading a single line from each file? Then you append
that into the "$write_directory/$directory" file. IIRC, you said
that you believe the output is actually more sporadic than that
though. Which I'm not following...

One thing to note is that <> and readline don't strip the newline
character from the line, so the additional one that you're
writing there is likely causing duplicates in the output. And for
future reference, non-ancient versions of Perl have a say()
alternative to print() that appends a newline for you.

>         close(WRITE) || die "Unable to close $write_file: $!\n";
>         close(READ) || die "Unable to close $file: $!\n";
>     }
> }
> 
> 1;

If that isn't enough to figure out your problem then I think
you're going to have to take another shot at explaining what it
is that you're trying to achieve, and what you're getting
instead. Many of us will not have the aforementioned book so you
should try to explain it to us assuming no external knowledge.

Regards,


-- 
Brandon McCaig <bamcc...@gmail.com> <bamcc...@castopulence.org>
Castopulence Software <https://www.castopulence.org/>
Blog <http://www.bamccaig.com/>
perl -E '$_=q{V zrna gur orfg jvgu jung V fnl. }.
q{Vg qbrfa'\''g nyjnlf fbhaq gung jnl.};
tr/A-Ma-mN-Zn-z/N-Zn-zA-Ma-m/;say'

Attachment: signature.asc
Description: Digital signature

Reply via email to