Reputation: 13
The below mentioned is throwing the following error upon execution-:
Global symbol "@files" requires explicit package name at ./q1.pl line 6.
Global symbol "$i" requires explicit package name at ./q1.pl line 6.
Global symbol "@files" requires explicit package name at ./q1.pl line 17.
Can someone explain me how to mitigate this problem and help me to optimize the code further
#!/usr/bin/perl
use warnings;
use strict;
sub print_file {
open FILE, $files[$i];
while(my $line = <FILE>) {
print $line;
}
}
sub globdir {
my $dir = shift;
@files = glob "$dir/*";
$i = 0;
while($i <= $#files) {
print("Files in the directory $files[$i] \n");
$i++;
print_file $files;
}
}
globdir @ARGV;
Upvotes: 0
Views: 177
Reputation: 5927
Try it. This is also print the file name with its contents.
use warnings;
use strict;
my $dir ='Direcotry_name';
opendir("dir",$dir);
my @files = grep{m/.*\.txt/g} readdir("dir");
foreach (@files){
print "Filename is: $_";
open("file","$dir/$_");
my @ar = <file>;
print "@ar";
}
In this code line 4 regexp m/.*\.txt/
get the particular format file into the directory.
Upvotes: 0
Reputation: 35198
You should include use strict;
and use warnings;
at the top of EVERY perl script like you've done here.
One of the things that this will tell you is when you've failed to declare a variable with my
, which will assist you in avoiding simple spelling errors in your code.
Error:
Global symbol "@files" requires explicit package name at ./q1.pl line 6.
Fix by declaring the variable:
my @files = glob "$dir/*";
That should be enough information for you to fix the other errors in your code. However, I would like to recommend that you simplify your code to just the following:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $dir = shift;
for my $file (<$dir/*>) {
print "File in the directory: $file\n";
# Output File Contents:
open my $fh, '<', $file;
print <$fh>;
}
Upvotes: 1
Reputation: 9259
When you include the line use strict
Perl tells you about variables which you're using, but not declaring. The error about $i
is because you're using the variable $i
without declaring it. By changing the $i
to my $i
the first time you use it, you'll be OK.
$i = 0;
becomes
my $i = 0;
With @files
it's more complicated. You're using it in both functions print_file
and globdir
. To do this, you'll need to put a:
my @lines;
before the first function. But you probably don't want to do this. You're trying to pass the filename to print_file
as an argument, but not using it. To get the filename you're passing, in the code fore print_file
put:
my $filename = shift;
So you then get:
sub print_file {
my $filename = shift;
open FILE, $filename;
while(my $line = <FILE>) {
print $line;
}
}
and you don't need @files
in print_file
. But you also need to call the print_file
function with the name of the file, so you'll need:
print_file $files[$i];
and you'll need to put a my
before `@files'.
So we now have:
#!/usr/bin/perl
use warnings;
use strict;
sub print_file {
my $filename = shift;
open FILE, $filename;
while(my $line = <FILE>) {
print $line;
}
}
sub globdir {
my $dir = shift;
my @files = glob "$dir/*";
my $i = 0;
while($i <= $#files) {
print("Files in the directory $files[$i] \n");
$i++;
print_file $files[$i];
}
}
globdir @ARGV;
At the very least, this now runs, and does something close to what you want it to. There are quite a few more problems with it. See how you can improve it, and then ask here if you need any further help.
For the record, I'd probably tackle this problem something like this:
#!/usr/bin/perl
use warnings;
use strict;
sub print_file {
my $filename = shift;
if (open my $fh, '<', $filename) {
local $/;
print <$fh>;
}
}
sub globdir {
foreach my $dir (@_) {
foreach my $filename (glob "$dir/*") {
print "Contents of file $filename:\n";
print_file $filename;
print "\n";
}
}
}
globdir @ARGV;
If you read this through and understand how and why it's different from your answer, you'll probably learn quite a lot.
Upvotes: 0