#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0

    Please Review Perl Code for Simple Module


    Hi

    I received Perl Skill assessment from the company in which I have applied for Perl software Dev position. I have completed the test & submitted to them but I got the rejection.

    All the script was working fine, I am not sure the reason of the rejection. May be they expect more expertise in coding style or logic may be wrong not sure....

    I have couple of question....


    I have try to use as less as possible perl CPAN module in my code


    1. Write a simple Perl module that will contain all the necessary subroutines to do the
    following:
    • locate all files in a specified directory and sub-directories that are world writable
    • remove the world write permission without altering the user or group permissions
    Your final version may rely upon modules provided by CPAN, but if so your module must be
    packaged to ensure that any dependencies are installed. Usage of only Core Perl modules does
    not require packaging. Your module must use Perl solely for gathering and manipulating the file
    system permissions.
    2. Create and provide a small script which utilizes your module. It must accept the
    directory or directories to be searched on the command line. The script should
    operate in a verbose mode as specified by the “--verbose” flag.
    3. Write a test script for the aforementioned module that utilizes Test::More from CPAN.
    4. Create another script utilizing your module that takes an additional user argument.
    The searching and permission changes should occur with the effective UID of the
    user passed as an argument.


    I am not expert Perl Programmer but I am crazy to learn Perl

    I have attached the code

    Code:
    MYModule.pm
    #!/usr/bin/perl
    
    package MyModule;
    	use strict;
    	use warnings;
    	use File::stat;
    	require Exporter;
    	our @ISA = qw(Exporter);
    	our @EXPORT = qw(GetFiles FindWw RemWwPerm CheckUid Display_msg Usage );
    	my $Pmission	 = undef;
    	my $OCT_Pmission = undef; 
    	my $file		 = undef;
    	my $f_uid 		 = undef;
    	my @file_list	 = ();
    	my $verbose		 = 0;
    	my $User_ID	     = undef;
    	my $fmode	     = undef;
    	my $header       = 0;
    	my $status	     = 0;
    
    sub GetFiles{
    	
    	my $dir;
    	my @files;
    	my $Isdir;
    	my $Checkfile;
    	
    	$dir = shift;
    	$dir = $1 if($dir=~/(.*)\/$/);
    	@files = glob("$dir/*");
    				
    	foreach $Checkfile (@files){
    		$Isdir = 0;
    		$Isdir = 1 if -d $Checkfile;
    		$Isdir	? (GetFiles($Checkfile)) : (push (@file_list, $Checkfile)); 		
    	}
    	
    	return (@file_list);
    }
    
    sub FindWw { 					
    
    	my $flag = 0; 
    	my @Getbit;
    
    	$file = shift;	
    	$Pmission 	  = stat($file)->mode & 07777; 	
    	$OCT_Pmission = sprintf "%o", $Pmission; 
    	@Getbit = split//, $OCT_Pmission; 
    	
    	if ($Getbit[2] == 7 or $Getbit[2] == 2 or $Getbit[2] == 3 or $Getbit[2] == 6){ 
    		return $flag = 1; 
    	} 	
    }
    
    sub RemWwPerm { 				
        
    	$file 	 = shift;
    	$verbose = shift;
    	$User_ID = shift;
    	
    	$Pmission 	  = stat($file)->mode & 07777; 
    	$OCT_Pmission = sprintf "%o", $Pmission;
    	$f_uid        = stat($file)->uid;
    	$fmode        = $OCT_Pmission - 2;	
    	Display_msg($User_ID);	  
    	chmod oct($fmode) , $file; 	
    }
    
    sub CheckUid { 					
    	
    	$file 	  = shift; 
    	$User_ID  = shift;
    	$f_uid    = stat($file)->uid;
    				
    	return $status = 1, if ($f_uid == $User_ID);	
    }
    
    sub Display_msg{
    
    	#$User_ID = shift; 
    	
    	if (($header == 0) && ($verbose == 1)){
    	
    		print "FILENAME", " " x(35-length("FILENAME")), 
    			  "CURRENT FILE PERMISSION\t",
    			  "FILE PERMISSION CHANGETO"; 
    			  ($User_ID) ? print "\t USER ID\n" : print "\n";      
    			  $header = 1;
    	}
    	
    	if ($verbose == 1){
    		print $file," " x(40-length($file)), 
    		      $OCT_Pmission, " " x(35 -length($OCT_Pmission)), 
    		      $fmode        , " " x(22-length($fmode)) ;
    			 ($User_ID) ? print "$f_uid \n" : print "\n";
    			  
    			
    	}	
    }
    
    sub Usage {
    
    print<<EOF;
    
    $0 script is use to locate the world writable permission from the given diretorie(s)/file(s) and 
    remove the world writable permission without altering user or group permission.
    Search & permission change can also possible for specific UID, passed as an command-line argument.
    
    $0 uses MyModule.pm developed by Ankit Kotak
    Please see below usage for detail reference.     
    
    USAGE:
    Script can take three options.
    
    Options:
    
    	--verbose : Optional. Print All the file for which world writable permission 
    		    has been removed.
    			
    	--dir	  : Can specifiy any number of diretories & files followd by space
    		    E.g. $0 --dir Dir1 Dir2 file1 file 2 
    			
    	--uid	  : To Restrict the change for specific user id(s), supply file uid(s) followed by space
    		    E.g. $0 --dir Dir1 file1 Dir2 --uid UserID_1  UserID_2  UserID_3
    				
    	Example:
    	
    	perl $0 --verbose --dir Dir1 Dir2 file1 --uid UserID_1
    	perl $0 --dir Dir1 Dir2 file1 --uid UserID_1 UserID_2 --verbose
    
    EOF
    
    }
    
    1;

    Code:
    Checkfile.pl
    #!/usr/bin/perl 
    use strict; 
    use warnings; 
    use MyModule; 
    use Getopt::Long;
    
    my $verbose = '';	# option variable with default value (false)
    my @UsrID = ();	# option variable with default value (false)
    
    my @get_dir = (); 
    my @file_list; 
    my @all_files;
    my $get_files;
    my $uid = '';
    my $match_uid = '';
    my $test = '';
    my $task = '';
    my $file = '';
    GetOptions 
    	('verbose' 		=> \$verbose, 
    	 'uid:i{1,}' 	=> \@UsrID, 
    	 'dir=s{1,}' 	=> \@get_dir
    	) or Usage(), die ($!);
    	
    Usage(), if (!$verbose and !$uid and !@get_dir);
    
    #print "FILENAME"." " x(35-length("FILENAME"))."CURRENT FILE PERMISSION\tFILE PERMISSION CHANGETO\t USRID \n", if ($verbose & @UsrID);
    #print "FILENAME"." " x(35-length("FILENAME"))."CURRENT FILE PERMISSION\tFILE PERMISSION CHANGETO\n", if ($verbose & !@UsrID);		
    		
    if (@get_dir) {
        foreach $get_files (@get_dir) { 
    
    		if($get_files and (-d $get_files)){
    			@file_list = GetFiles($get_files); 
    			push (@all_files, @file_list);
    		}
    	
    		elsif($get_files and (-f $get_files)){
    			@file_list = $get_files;
    			push (@all_files, @file_list);
    		}
    	
    		else {
    			print "The dir/file name, \"$get_files\" not found.\nPlease Check the file or dir name.\n";
    		}
    	} 
    }
    
    
    	foreach $file (@all_files){ 
    			
    		if (@UsrID){
    			foreach $uid(@UsrID){
    				$match_uid = CheckUid($file, $uid);	
    				$test = FindWw($file) , if $match_uid;
    				$task = RemWwPerm($file, $verbose, $uid), if $test; last;
    			
    			}
    		}	
    		else{
    			$test = FindWw($file);
    			$task = RemWwPerm($file, $verbose), if $test;
    		} 	
    	}


    I appreciate if someone can review my code and provide some guidance so I can improve my coding style....
  2. #2
  3. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,260
    Rep Power
    1810
    I'll get things started very gently; I don't have a lot of time to read through the whole module.

    First, great job creating working code to do the job! I think that's the most important point. The person who could help you most would be the person at the job who reviewed your code. See if there is some way you can talk to them and get some feedback. That would be most helpful.

    There are some other sources though. First, there's a perl style guide at the perl.org website.

    There's a book called Perl Best Practices which was used as the basis for the Perl::Critic module which you can used to check your code.

    Here's a PDF link to the rules: http://refcards.com/docs/vromansj/pe...s/refguide.pdf

    I wouldn't consider all the rules to be essential, but it's a defined style guide you can use as the basis of evaluating your code. Nice thing about it is, you don't even have to use the module locally. You can test your code at the following website:

    http://perlcritic.com

    Just upload your script and see the results. Here's what it has to say about MYModule.pm on the gentle setting:

    Loop iterator is not lexical at line 33, column 2. See page 108 of PBP. Severity: 5
    Integer with leading zeros: "07777" at line 48, column 37. See page 58 of PBP. Severity: 5
    Integer with leading zeros: "07777" at line 63, column 37. See page 58 of PBP. Severity: 5
    I'll offer my critique, but take it with a grain of salt. I'm not a professional programmer, I just code in support of my other job functions. No one in my workplace reviews or critiques what I write:

    ---

    This first criticism: "Loop iterator is not lexical at line 33, column 2." refers to this sort of style:

    Code:
    my $Checkfile;	
    foreach $Checkfile (@files){
    but this is preferred:
    Code:
    foreach my $Checkfile (@files){
    And that is the first thing that caught my eye. You have a lot of variables which have essentially been declared in a global context within the module. The long definition of variables at the beginning appears to be unnecessary, as each could be declared within their subroutines as they are needed.

    Example:
    Code:
    sub RemWwPerm { 				
    	my ($file, $verbose, $User_ID) = @_;
    The only other likely change from something I would write would be I wouldn't use Exporter. Exporting isn't bad; it's an established perl practice. I just see no need to export functions into the larger namespace when I could simply use an object style and call all my methods that way. I consider it less work, too.

    ---

    Hope you won't be discouraged. It may be that they had an applicant with much more experience. If they won't tell you then there is no way to know.

    I think you're doing well, and I wish you the best of luck!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0
    Hi Keath,

    Thank you for your feedback & guidance to for the Perl coding style sources.

    I am not sure but I was suppose to use public & private variable concept here, so what ever variable I have defined at the beginning are shared by all the subroutine(method) & whatever variable are defined inside the subroutine are specifically belongs to that sub.

    May be I'll get better inside after reviewing perl practice & code guideline.

    Thank again for your inputs....


    Originally Posted by keath
    I'll get things started very gently; I don't have a lot of time to read through the whole module.

    First, great job creating working code to do the job! I think that's the most important point. The person who could help you most would be the person at the job who reviewed your code. See if there is some way you can talk to them and get some feedback. That would be most helpful.

    There are some other sources though. First, there's a perl style guide at the perl.org website.

    There's a book called Perl Best Practices which was used as the basis for the Perl::Critic module which you can used to check your code.

    Here's a PDF link to the rules: http://refcards.com/docs/vromansj/pe...s/refguide.pdf

    I wouldn't consider all the rules to be essential, but it's a defined style guide you can use as the basis of evaluating your code. Nice thing about it is, you don't even have to use the module locally. You can test your code at the following website:

    http://perlcritic.com

    Just upload your script and see the results. Here's what it has to say about MYModule.pm on the gentle setting:



    I'll offer my critique, but take it with a grain of salt. I'm not a professional programmer, I just code in support of my other job functions. No one in my workplace reviews or critiques what I write:

    ---

    This first criticism: "Loop iterator is not lexical at line 33, column 2." refers to this sort of style:

    Code:
    my $Checkfile;	
    foreach $Checkfile (@files){
    but this is preferred:
    Code:
    foreach my $Checkfile (@files){
    And that is the first thing that caught my eye. You have a lot of variables which have essentially been declared in a global context within the module. The long definition of variables at the beginning appears to be unnecessary, as each could be declared within their subroutines as they are needed.

    Example:
    Code:
    sub RemWwPerm { 				
    	my ($file, $verbose, $User_ID) = @_;
    The only other likely change from something I would write would be I wouldn't use Exporter. Exporting isn't bad; it's an established perl practice. I just see no need to export functions into the larger namespace when I could simply use an object style and call all my methods that way. I consider it less work, too.

    ---

    Hope you won't be discouraged. It may be that they had an applicant with much more experience. If they won't tell you then there is no way to know.

    I think you're doing well, and I wish you the best of luck!
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,940
    Rep Power
    1225
    There are a number of issues with that code but this will not be a complete review/critique.

    I have try to use as less as possible perl CPAN module in my code
    IMO, that was your first mistake. You should try to take advantage of cpan modules especially if they are core modules. For example, your GetFiles() sub would be much better if you use File::Find instead of rolling your own recursive function.

    Your choice of names for your subs and a number of the vars are questionable. CamelCase names are more difficult to read. With multi word names use an underscore to separate the words.

    Names should also accurately describe what the var holds or what the sub does. For example, the FindWw() sub would be better named is_world_writable().

    Module usage statements are best handled with POD documentation and I'd even seriously consider using POD in the scripts as well. POD::Usage goes well with Getopt::Long. http://search.cpan.org/~jv/Getopt-Lo...and_help_texts

    A filename of Checkfile.pm implies that it's a module but it's not. You should use the .pl extension instead of .pm for scripts.

    The Checkfile script has several questionable syntax issues as well as some logic issues.
    For example:
    Code:
    Usage(), if (!$verbose and !$uid and !@get_dir);
    The comma is unnecessary and unwanted. In order for the Usage() sub to execute all 3 of those vars need to be undefined or at least evaluate to false. I seriously doubt that was what you really intended.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0
    Hi ,

    Thanks a lot for carefully reviewing my code.

    - The reason that I have used as less as possible CPAN module as, this was the assessment test, like in interview mostly they expect that candidate create their own module.

    - While developing this script I have use first File::Find module but later I have replace it with my own subroutine. May be my subroutine could not completely grab the file (later I realized link file which basically link/reference to some other file/directory within that directory or some different directory) . Not sure.

    - Also I need to review what is the difference between my subroutine, GetFiles() & find CPAN one.

    -----------------------------------------------

    Thank you for your suggestion for variable & subroutine name
    ---------------------------------------------------------
    Checkfile.pm was just typo in this post but actually I have used .pl extension for my script. I have updated it in my post. Thanks that.
    --------------------------------------------------------

    Code:
    Usage(), if (!$verbose and !$uid and !@get_dir);
    Yes, that is write I was suppose to invoke Usage(), when someone just try to run the script without option. Can you please elaborate something more here apart from comma ",", is there anything else that is unnecessary.



    I really appreciate your time to review my code.

    Thanks
    Ankit Kotak
  10. #6
  11. No Profile Picture
    PerlGuy
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2001
    Posts
    720
    Rep Power
    42
    Maybe they wanted to see an OO approach. I'm would've thought they'd say, but I suppose you never know.
    - dsb -
    Perl Guy
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    30
    Rep Power
    1
    Hi,
    I agree with those that have commented before now. Your variables should be declared very close to where they are needed.
    For your module why use #!/usr/bin/perl simply just start with package Module_name;. Lastly, I didn't see the test script question 3 asked you to write, using Test::More.
    3. Write a test script for the aforementioned module that utilizes Test::More from CPAN.
    That might just be want they want to see. But of course, I can't tell.

    It also good to use perltidy to make your code very readable.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0
    Sorry actually I have not uploaded that script, as I've written that script but may be not as good as it should be.

    Code:
    t\MyModule.t
    #!/usr/bin/perl
    use strict;
    use warnings;
    use MyModule;
    
    use Test::More qw(no_plan);
    
    use_ok ( 'MyModule'); #test #1
    use_ok ( 'MyModule', 'GetFiles', 'FindWw', 'RemWwPerm', 'CheckUid', 'Display_msg', 'Usage' ); #test #2
    
    #test 3 &4
    
    can_ok ( 'MyModule', 'GetFiles', 'FindWw', 'RemWwPerm', 'CheckUid', 'Display_msg', 'Usage' ); #test #3
    can_ok ( __PACKAGE__, 'GetFiles', 'FindWw', 'RemWwPerm', 'CheckUid', 'Display_msg', 'Usage'); #test #4
    
    #  TestCases for testing functions
    is(GetFiles('ScriptTest/'),16 , "GetFiles Good"); #test #5
    
    is(FindWw('find_uid.pl'), 1, "FindWw Good" ); #test #6:    Provided file is world Writable files so it return 1;
    isnt(FindWw('GetFiles.pl'), 0, "FindWw Good" ); #test #7: Provided file is not world Writable so it return 0;
    
    is(RemWwPerm('find_uid.pl',1, '1001'), 1, "RemWwPerm with Verbose" ); #test #8: Provided Given files world Writable
    is(RemWwPerm('testModule.pl',0, '1001'), 1, "RemWwPerm without Verbose" ); #test #9: Without verbose output
    
    is(CheckUid('find_uid.pl', '1001'),1, "CheckUid actual file UID");#test #10: with actual UID of the file
    isnt(CheckUid('GetOpt.pl', '1002'),1, "CheckUid wrong file UID");#test #11: with wrong UID of the file
    Thanks for the info about perltidy, I'll see it in detail for my future script
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,940
    Rep Power
    1225
    Others have brought up the suggestion/recommendation of writing an OO module rather than a functional module and suggested that's what the interview wants to see. My interpretation is that they intentionally did not specify which one they would like to see so that they could use 1 set of requirements to evaluate multiple levels of applicants.

    An entry level perl programmer would in most cases use the functional interface but a more experienced programer would most likely use the OO interface. Using OO is a little more advanced/complex.

    Their reasoning between leaving the choice between the 2 interface methods to the applicant would also carry down to see what choices the applicant made regarding cpan modules. An entry level person would as was done in this case try to avoid using cpan modules as much as possible but a slightly more experienced person would use a limited number of core modules. An experienced person would use well known and proven non core modules which would then require the additional task of packaging them up for the distribution.

    There is no wrong answer to any of those choices, but those choices go a long way in filtering applicants into the appropriate category.

    Lets take a look at the first requirement.
    • locate all files in a specified directory and sub-directories that are world writable
    Your GetFiles() sub fails to meet that requirement because it ignores the qualifying clause "that are world writable". Your FindWw() sub addresses that qualifying clause, but the GetFiles() sub needlessly built an array of ALL files. For the sake of argument lets say that the array holds 10,000 files but only 10 of them are world writable. So, why capture and later process/filter so many files that don't meet the stated requirement?

    Code:
    Usage(), if (!$verbose and !$uid and !@get_dir);
    Yes, that is write I was suppose to invoke Usage(), when someone just try to run the script without option.
    It's unclear to me if you meant that all 3 of those vars are required. As is, the Usage() sub will only be called if ALL 3 are missing. If --verbose was supplied but the others weren't then the script would fail and the Usage() sub would NOT be called.

    BTW, the Usage() sub should be in the main script, not the module. Or better yet, use the Pod::Usage module.
    Last edited by FishMonger; November 27th, 2013 at 11:44 AM.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Posts
    832
    Rep Power
    496
    Originally Posted by kotak86
    I am not sure but I was suppose to use public & private variable concept here, so what ever variable I have defined at the beginning are shared by all the subroutine(method) & whatever variable are defined inside the subroutine are specifically belongs to that sub.
    This is widely considered as a poor practice, which can lead to insidious bugs. You should declare your variables within the lexical scope where they need to be, for example within a function. I would even say that they should be declared within the smallest possible scope. So that if you have a function and, within that function a while loop, if some variable is used only within the loop, declare it within the loop, and not even at the top of the loop if it is used quite later in the loop.

    I am not claiming that my code should be a model, but, as an example of the above, take a look at a small and quick bit of code I wrote in answer to a question on a Perl forum:

    Perl Code:
    use strict;
    use warnings;
     
    my $total_count;
    my @files = glob "./s*.pl";
    for my $file (@files) {
    	my $count = getcount($file);
    	print "$file \t $count \n";
    	$total_count += $count;
    }
     
    sub getcount {
    	# ... omitted for brevity
    	return $.;
    }
    print "Total size = $total_count lines.\n";


    As you can see, $file and $count a local to the for loop, because they are not needed anywhere else. The $total_count variable, on the other hand is declared beforehand, because I need it after the loop is completed.

    Just by looking at all your variable declarations at the top, I would be inclined to think that you are not an experienced Perl programmer. (This is not a critique, I was also doing that when I picked up Perl).
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0
    Thanks a lot and It gives more insight about it & force to review document about the standard code practices.

    Originally Posted by Laurent_R
    This is widely considered as a poor practice, which can lead to insidious bugs. You should declare your variables within the lexical scope where they need to be, for example within a function. I would even say that they should be declared within the smallest possible scope. So that if you have a function and, within that function a while loop, if some variable is used only within the loop, declare it within the loop, and not even at the top of the loop if it is used quite later in the loop.

    I am not claiming that my code should be a model, but, as an example of the above, take a look at a small and quick bit of code I wrote in answer to a question on a Perl forum:

    Perl Code:
    use strict;
    use warnings;
     
    my $total_count;
    my @files = glob "./s*.pl";
    for my $file (@files) {
    	my $count = getcount($file);
    	print "$file \t $count \n";
    	$total_count += $count;
    }
     
    sub getcount {
    	# ... omitted for brevity
    	return $.;
    }
    print "Total size = $total_count lines.\n";


    As you can see, $file and $count a local to the for loop, because they are not needed anywhere else. The $total_count variable, on the other hand is declared beforehand, because I need it after the loop is completed.

    Just by looking at all your variable declarations at the top, I would be inclined to think that you are not an experienced Perl programmer. (This is not a critique, I was also doing that when I picked up Perl).
  22. #12
  23. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    6
    Rep Power
    0
    Hi...

    First of all thanks to finding bugs about GetOpt, yes I have code the way usage will call only if none of the argument is passed - but that is wrong.

    Also I can understood your point to unnecessarily process & create the arrays which return by GetFiles().


    Thank you for your both comments.



    Originally Posted by FishMonger
    Others have brought up the suggestion/recommendation of writing an OO module rather than a functional module and suggested that's what the interview wants to see. My interpretation is that they intentionally did not specify which one they would like to see so that they could use 1 set of requirements to evaluate multiple levels of applicants.

    An entry level perl programmer would in most cases use the functional interface but a more experienced programer would most likely use the OO interface. Using OO is a little more advanced/complex.

    Their reasoning between leaving the choice between the 2 interface methods to the applicant would also carry down to see what choices the applicant made regarding cpan modules. An entry level person would as was done in this case try to avoid using cpan modules as much as possible but a slightly more experienced person would use a limited number of core modules. An experienced person would use well known and proven non core modules which would then require the additional task of packaging them up for the distribution.

    There is no wrong answer to any of those choices, but those choices go a long way in filtering applicants into the appropriate category.

    Lets take a look at the first requirement.

    Your GetFiles() sub fails to meet that requirement because it ignores the qualifying clause "that are world writable". Your FindWw() sub addresses that qualifying clause, but the GetFiles() sub needlessly built an array of ALL files. For the sake of argument lets say that the array holds 10,000 files but only 10 of them are world writable. So, why capture and later process/filter so many files that don't meet the stated requirement?

    Code:
    Usage(), if (!$verbose and !$uid and !@get_dir);
    It's unclear to me if you meant that all 3 of those vars are required. As is, the Usage() sub will only be called if ALL 3 are missing. If --verbose was supplied but the others weren't then the script would fail and the Usage() sub would NOT be called.

    BTW, the Usage() sub should be in the main script, not the module. Or better yet, use the Pod::Usage module.

IMN logo majestic logo threadwatch logo seochat tools logo