1

I would like to process files recursively.

I have a config file, and this config file can include an "include" statement. Once the include-statment is identified, the file shall be processed. It could happen, that in the file processed again an include-statement can show up.

So something like this:

  • config file
  • process lines of first level
  • include file (process now)
    • process line of second level
    • -include file (process now) - process and close
    • process further lines of second level
    • close file
  • process more lines of first level
  • close file

For this to manage I have created a subroutine: Update ---- call for sub updated!

my $av_fn_FH;
my $av_tmp_LINE;
my @av_arr_FN;
sub processfile
{
  open($av_fn_FH, "<", "$_[0]")
  while($av_tmp_LINE = readline($av_fn_FH)) 
  { 
    if ( substr($av_tmp_LINE,0,7) eq "include" )
    {
      @av_arr_FN = split(" ", $av_tmp_LINE); # get the filename from the include statement
      processfile($av_arr_FN[1]); # process the include file
    }
    # do something with "normal" lines
  }
  close($av_fn_FH);
}

This recursive calling of the subroutine does not work. Once comming back from the subroutine the HANDLE is reported as closed.

The docu for the open statement says: "Associates an internal FILEHANDLE with the external file specified by EXPR." I expected the FILEHANDLE as unique!

I would apreciate some hints how to get this done!

averlon
  • 325
  • 3
  • 14
  • 1
    `sub processfile($av_arr_FN[1]);` **does not** call the sub! Maybe try a bit harder with your code, using `use warnings; use strict;`, too. – U. Windl Aug 23 '23 at 12:55
  • @U.Windl; you are naturally right. Was a typo - already corrected in real world. Anyhow. This does not solve the problem! I am currently working on a solution with module "FileHandle". This seems to work but not fully tested up to now! – averlon Aug 23 '23 at 14:30

1 Answers1

2

Your filehandle is declared outside of the subroutine; so you over-write the value when you open a new config file, and then close it.

sub processfile
{
    open(my $fh, "<", $_[0])
        or die "Can't open $_[0]: $!";

    while(my $line = readline($fh)) { 
        if ($line =~ /^include\s+(\S+)/) {
            # $1 is the filename after "include "
            processfile($1);   # process the include filename
            next; # skip "normal" stuff below
        }
        # do something with "normal" lines
    }
    close($fh); # optional; closes anywhen when $fh goes out of scope
}

In general, you want to declare your variables in as small a scope as possible where they're actually used.

U. Windl
  • 3,480
  • 26
  • 54
Jim Davis
  • 5,241
  • 1
  • 26
  • 22