How to retuen a value while using File::Find

Hi,
I have two subroutines

sub xcheck
{
  ## get the $directory after some code lines.
  find (\&xlength , $directory);

}

sub xlength
  {
   
  my $file = $File::Find::name;
  if(-f $file)
   {
   open(FILE, "<$file") || die "Can't open $file $!\n";
   my @lines = <FILE>;
   close(FILE);
   }
    ## do some operation on each of the files in $directory.
    push (@errorMessage, "error messages");
 return   @errorMessage;     ##==> I want this return value.
 }
 
 
 How can I return a value while using find?
 I have tried
 find (\&xlength(\@errorMessage), $directory);
 
 and updating the reference in xlength.
 But File::Find doesn't work then.
 
Thanks

Sini
sini_mAsked:
Who is Participating?
 
kanduraConnect With a Mentor Commented:
xlength operates on a single filename, so it has no business returning the entire array. I can see why you'd want it to, though. This is probably the easiest way:


    use File::Find;
    use strict;
   
    print map { $_.$/ } xcheck('.');
   
    sub xcheck
    {
        my $directory = shift;
        ## get the $directory after some code lines.
        my @errorMessage;
        find (sub { push @errorMessage, xlength($File::Find::name) }, $directory);
        return @errorMessage;
    }
   
    sub xlength {
        my $file = shift;
        if(-f $file )
        {
            open(my $fh, "<$file") or return "$file: $!";
           
            # @lines = <$fh>;
            #process lines
           
            # a sample file test to show how to return errors
            return "$file: not /a/" unless /a/;
        }
   
        return;    
    }
   
0
 
inq123Commented:
Hi sini_m,

One possibility is to declare a global arrayref variable and use that variable in place of the @errorMessage in your xlength().  That way you just read the content of the arrayref after calling find() and you don't have to worry about returning any data from xlength.

Cheers!
0
 
ozoCommented:

sub xcheck
{
  local @errorMessage;
  ## get the $directory after some code lines.
  find (\&xlength , $directory);
  return   @errorMessage;     ##==> I want this return value.
}

sub xlength
  {
   
  my $file = $File::Find::name;
  if( -f )
   {
   open(FILE, "<$file") || die "Can't open $file $!\n";
   my @lines = <FILE>;
   close(FILE);
   }
    ## do some operation on each of the files in $directory.
    push (@errorMessage, "error messages");
 }
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

 
sini_mAuthor Commented:
Hi,

I just tried out ozo's comment.
---------------
Global symbol "@errorMessage" requires explicit package name at test.pl line 5.
Execution of test.pl aborted due to compilation errors.
--------------

I am using use strict;

 inq123, I failed to mention I shouldn't be using any global variables. These subroutines go into a package. Can't use any package wide variables. Is 'local' like a global variable?

I am going to try out kandura's comment.
Thanks for the help.

Sini


0
 
sini_mAuthor Commented:
Hi,

Kandura's solution did the work for me.

sub init
{
  print map { $_.$/ } xcheck('.');
}

&init;

Thanks for all the solutions offered.
Sini
0
 
ozoCommented:
use strict;
use warnings;
use File::Find;
my $directory='testdir';
sub xcheck
{
  local @::errorMessage;
  ## get the $directory after some code lines.
  find (\&xlength , $directory);
  return   @::errorMessage;     ##==> I want this return value.
}

sub xlength
  {
   
  my $file = $File::Find::name;
  if( -f )   {
   open(FILE, "<$_") || die "Can't open $file $!\n";
   my @lines = <FILE>;
     close(FILE);
   }
    ## do some operation on each of the files in $directory.
    push (@::errorMessage, "error messages");
 }

print join"\n",xcheck();
0
 
inq123Commented:
sini_m, if you can't use global, then I prefer ozo's solution (no offense to Kandura's nice solution).  

local is not global.  It localizes the variable to the current lexical scope AND all the subs called after the local declaration.  So it's kinda like a localized global and it'd better solve your package concerns.  

But frankly, even if you put those subs into a package, there's no rule that says global variables cannot be used.  If you declare these global variables with 'my', then the other packages and calling programs of your package won't be able to access it either (no accidental usage or non-permitted access).  

Further, I personally think the access control in Perl is maybe "nice style" but in actuality ridiculous, since its source code is in plain daylight for everyone to see/change.
0
 
sini_mAuthor Commented:
Hi,

It is a package a lot of people are developing. We write subroutines for various 'checks' and put them into an existing package. It is kind of a continuing process.  I will try out ozo's new comment. If

local @::errorMessage  and
@::errorMessage

are different in behaviour, maybe I could use this.

Thanks
Sini
0
 
inq123Commented:
I see.  But wouldn't it be better to have each person/group to contribute to a separate package?  It sounds (more than) a bit messy to have everybody contributing to one big test package.
0
 
sini_mAuthor Commented:
Hi inq123,

Yes, It is not the best solution. But an 'engine' that runs theses rules takes into account only a couple of packages, so we have to fit everything into it. Or redesign the engine.
0
 
inq123Commented:
Why not let your engine take in a Config.pm, in which all the new test modules are added.  Each test programmer maintains his/her own modules, just add the module names to Config.pm.  All the functions can be exported in those separate test modules and any package variables can be used safely.  Requires little effort to do it this way.
0
 
sini_mAuthor Commented:
Hi inq123,

Guess we could consider it. There might be objection to any change now, but let me see. :) Thanks.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.