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'
signature.asc
Description: Digital signature