in reply to File not opening, but no error report

Now is there something obviously normal about this strange output...?

If your first debug print statement is uncommented you should see every line of every file you read but if only the second is uncommented you may well see something like the sample you provided.

You have two loops: an outer loop for each file in the directory and an inner loop for each line in the current file. On each iteration of the inner loop you push the current line onto @lines. So @lines eventually contains all the lines from all the files. Initially $lines[31] is undefined, so your second debug print statement will print nothing (but you should get a warning like "Use of uninitialized value in concatenation (.) or string at ..."), but after you have read 32 lines it will have a value and it will never change, so your second debug print will then print the same string each time through the loop.

Following is an example you might consider. It has a few advantages and some disadvantages:

#!/usr/bin/perl # use strict; use warnings; use HTML::Template; use Data::Dumper; my $path = '/mnt/data/Programming'; my $links = "$path/links.html"; my @strings = qw( file split opendir push sort sub % STDIN ); my %match; # Scan all the files and build a HoHoA # indexed by search string and file name # and containing the matched text. foreach my $file (glob("$path/*.pl")) { next if($file eq $links); next unless(-f $file); open(IN, '<', $file) or die "$file: $!"; my $content = do { local $/; <IN> }; close(IN); foreach my $string ( @strings ) { if(my @matches = ($content =~ m/((?:^.*\n)?(?:^.*$string.*$)+( +?:\n.*$)?)/mg)) { $match{$string}{$file} = join("\n...\n", @matches); } } } # Reorganize the contents of %match into display order # and the format required by HTML::Template: # [ # { # string => "%", # files => [ # { # file => "/full/path/of/filex", # text => "matched text of file x", # }, # { # file => "/full/path/of/filey", # text => "matched text of file y", # }, # ... # ], # }, # { # string => "sub", # files => [ # { # file => "/full/path/of/filez", # text => "matched text of file z", # }, # ... # ], # }, # ... # ] my @params; foreach my $string (sort keys %match) { my @files; foreach my $file (sort keys %{$match{$string}}) { push(@files, { file => $file, text => $match{$string}{$file} } +); } push(@params, { string => $string, files => \@files }); } # merge the data with the template and save it my $page = HTML::Template->new( filehandle => *DATA,); $page->param(STRINGS => \@params,); open(OUT, '>', $links) or die "$links: $!"; print OUT $page->output; close(OUT); __DATA__ <html> <head><title>My Program Links</title></head> <body> <TMPL_LOOP NAME=STRINGS> <h1><TMPL_VAR ESCAPE=HTML NAME=STRING></h1> <TMPL_LOOP NAME=FILES> <a href="<TMPL_VAR NAME=FILE>"><TMPL_VAR ESCAPE=HTML NAME=FILE></a> <pre> <TMPL_VAR ESCAPE=HTML NAME=TEXT> </pre> </TMPL_LOOP> </TMPL_LOOP> </body> </html>