The big issue with tweaking @ARGV is that it is a global variable. Also, you should be aware that while (<>)
has special magic attributes. (reading each file in @ARGV
or processing STDIN
if @ARGV
is empty, testing for definedness rather than truth). To reduce the magic that needs to be understood, I would avoid it, except for quickie-hack-jobs.
You can get the filename of the current file by checking $ARGV
.
You may not realize it, but you are actually affecting two global variables, not just @ARGV
. You are also hitting $_
. It is a very, very good idea to localize $_
as well.
You can reduce the impact of munging globals by using local
to localize the changes.
BTW, there is another important, subtle bit of magic with <>
. Say you want to return the line number of the match in the file. You might think, ok, check perlvar and find $.
gives the linenumber in the last handle accessed--great. But there is an issue lurking here--$.
is not reset between @ARGV
files. This is great if you want to know how many lines total you have processed, but not if you want a line number for the current file. Fortunately there is a simple trick with eof
that will solve this problem.
use strict;
use warnings;
...
searchDir( 'foo' );
sub searchDir {
my $dirN = shift;
my $pattern = shift;
local $_;
my @fileList = grep { -f $_ } glob("$dirN/*");
return unless @fileList; # Don't want to process STDIN.
local @ARGV;
@ARGV = @fileList;
while(<>) {
my $found = 0;
## Search for pattern
if ( $found ) {
print "Match at $. in $ARGV\n";
}
}
continue {
# reset line numbering after each file.
close ARGV if eof; # don't use eof().
}
}
WARNING: I just modified your code in my browser. I have not run it so it, may have typos, and probably won't work without a bit of tweaking
Update: The reason to use local
instead of my
is that they do very different things. my
creates a new lexical variable that is only visible in the contained block and cannot be accessed through the symbol table. local
saves the existing package variable and aliases it to a new variable. The new localized version is visible in any subsequent code, until we leave the enclosing block. See perlsub: Temporary Values Via local().
In the general case of making new variables and using them, my
is the correct choice. local
is appropriate when you are working with globals, but you want to make sure you don't propagate your changes to the rest of the program.
This short script demonstrates local:
$foo = 'foo';
print_foo();
print_bar();
print_foo();
sub print_bar {
local $foo;
$foo = 'bar';
print_foo();
}
sub print_foo {
print "Foo: $foo\n";
}