(unintialized value in number lt (<) at) error

(unintialized value in number lt (<) at) error

am 02.08.2011 15:02:24 von Jason Forget

Hello all,

I am receive the unintialized value in number lt (<) at error when
running the below perl script. The error is indicated on line 34.
The challenge I face is that this script was written by one person;
modified by another and I am tasked to fix it. I am a beginner to
perl scripting. From what I've read, the (<) needs to be
initialized...???

The script is called to delete files from a directory beyond a certain
date.

#!\Perl\bin\perl -w
# usage: DeleteFiles.pl

<#days>
#use strict;

# sub recurse($) {
sub recurse {
# my($path) = @_;
my($path) = $_[0];
my($days) = $_[1];
my($seconds) = $days*24*60*60;
## append a trailing / if it's not there
$path .= '\\' if($path !~ /\/$/);
print "Set to delete from ... $path\n";
##$path = '\\Working_Temp\\';
##print "Hard coded to delete from: $path\n";
## print the directory being searched
##print $path,"\n";
open (MYFILE, '>>deletes.bat');

## loop through the files contained in the directory
for my $eachFile (glob($path.'*')) {

## if the file is a directory
if( -d $eachFile) {
## pass the directory to the routine ( recursion )
print "recursing $eachFile\n";
recurse($eachFile, $days);
} else {

## print the file ... tabbed for readability
my $now = time;
my @stat = stat("$eachFile");
if ($stat[9] < ($now - $seconds))
{
#print "del $eachFile\n";
print MYFILE "del \"$eachFile\"\n";
unlink("$eachFile");
print "Done.\n";
} print "\t",$eachFile,"\n";
}
}

}

## initial call ... $ARGV[0] is the first command line argument
recurse($ARGV[0], $ARGV[1]);
#close (MYFILE);


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: (unintialized value in number lt (<) at) error

am 02.08.2011 19:08:13 von Rob Dixon

On 02/08/2011 14:02, Jason Forget wrote:
> Hello all,
>
> I am receive the unintialized value in number lt (<) at error when
> running the below perl script. The error is indicated on line 34.
> The challenge I face is that this script was written by one person;
> modified by another and I am tasked to fix it. I am a beginner to
> perl scripting. From what I've read, the (<) needs to be
> initialized...???
>
> The script is called to delete files from a directory beyond a certain
> date.

Hi Jason

The Perl program that you have adopted has a lot of problems, some of
which I describe below. But skip to the end of the mail to help correct
the error that you describe.

> #!\Perl\bin\perl -w
> # usage: DeleteFiles.pl

<#days>
> #use strict;

/Never/ disable strict. And, rather than using -w in the #! line, add

use warnings;

here.

> # sub recurse($) {
> sub recurse {

That is correct. never use subroutine prototypes except in very special
circumstances.

> # my($path) = @_;
> my($path) = $_[0];
> my($days) = $_[1];

None of these are correct. Write

my ($path, $days) = @_;

> my($seconds) = $days*24*60*60;

That will work, but should be

my $seconds = $days*24*60*60;

> ## append a trailing / if it's not there
> $path .= '\\' if($path !~ /\/$/);
> print "Set to delete from ... $path\n";
>
> ##$path = '\\Working_Temp\\';
> ##print "Hard coded to delete from: $path\n";
> ## print the directory being searched
> ##print $path,"\n";
> open (MYFILE, '>>deletes.bat');

It is far better to use lexical file handles, and in any case you must
check the status of an file open. So

open my $myfile, '>>', 'deletes.bat' or die "Unable to append to 'deletes.bat': $!";

> ## loop through the files contained in the directory
> for my $eachFile (glob($path.'*')) {
>
> ## if the file is a directory
> if( -d $eachFile) {
> ## pass the directory to the routine ( recursion )
> print "recursing $eachFile\n";
> recurse($eachFile, $days);
> } else {
>
> ## print the file ... tabbed for readability
> my $now = time;
> my @stat = stat("$eachFile");

It is wrong in almost all circumstances to enclose a scalar variable in
quotes. See below regarding this line.

> if ($stat[9]< ($now - $seconds))
> {
> #print "del $eachFile\n";
> print MYFILE "del \"$eachFile\"\n";

If you have used a lexical file handle, then this will read

print $myfile "del \"$eachFile\"\n";

> unlink("$eachFile");

As before, this should be

unlink $eachFile;

> print "Done.\n";
> } print "\t",$eachFile,"\n";
> }
> }
>
> }
>
> ## initial call ... $ARGV[0] is the first command line argument
> recurse($ARGV[0], $ARGV[1]);
> #close (MYFILE);

There is no need to excplicitly close any input file handles, but this
is an output file handle and it is possible that the file may not be
written properly on closure. You should write

close $myfile or die "Failed to close .bat file: $!";




As for the "unintialized value" error:

Line 34 reads

if ($stat[9]< ($now - $seconds)) {

and your error message suggest that there is no element [9] in the @stat
array. That array is assigned at line 32

my @stat = stat("$eachFile");

so there is a problem with getting the status of the file named
$eachFile. As a first step, you should change that line to

my @stat = stat $eachFile or die "stat failed on '$eachFile': $!";

to give you an indication about why the @stat array is empty.

I hope this helps,

Rob

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: (unintialized value in number lt (<) at) error

am 02.08.2011 19:12:26 von Shlomi Fish

Hi Jason,

I'm going to comment on your code, and hopefully point to problems in it.

On Tue, 2 Aug 2011 06:02:24 -0700 (PDT)
Jason Forget wrote:

> Hello all,
>
> I am receive the unintialized value in number lt (<) at error when
> running the below perl script. The error is indicated on line 34.
> The challenge I face is that this script was written by one person;
> modified by another and I am tasked to fix it. I am a beginner to
> perl scripting. From what I've read, the (<) needs to be
> initialized...???
>
> The script is called to delete files from a directory beyond a certain
> date.
>
> #!\Perl\bin\perl -w
> # usage: DeleteFiles.pl

<#days>
> #use strict;

Why is "use strict;" commented out? Every module should have "use strict;" and
"use warnings;". See:

http://perl-begin.org/tutorials/bad-elements/

>
> # sub recurse($) {
> sub recurse {

If you were going to get rid of the prototype (which is not a good idea - see
the above link) please don't comment-out the original line because it just
introduces clutter.

> # my($path) = @_;
> my($path) = $_[0];
> my($days) = $_[1];

This should be written as:

my ($path, $days) = @_;

You're also missing a space after the my.
> my($seconds) = $days*24*60*60;
> ## append a trailing / if it's not there
> $path .= '\\' if($path !~ /\/$/);

The comment is not helpful, and introduces more clutter and a "/" is not a "\".
You also probably want to use "/" (slashes) instead of "\\" if you want your
script to be portable to UNIXes and other non-Windows platforms. Or use
File::Spec:

http://perl-begin.org/uses/sys-admin/

> print "Set to delete from ... $path\n";
> ##$path = '\\Working_Temp\\';
> ##print "Hard coded to delete from: $path\n";
> ## print the directory being searched
> ##print $path,"\n";

So many commented out lines so much clutter.

> open (MYFILE, '>>deletes.bat');
>

Well, your indentation is erratic, and furthermore, you're opening the same
global filehandles, several times for each time the function is called. See
what I say about open style on http://perl-begin.org/tutorials/bad-elements/

> ## loop through the files contained in the directory
> for my $eachFile (glob($path.'*')) {
>
> ## if the file is a directory
> if( -d $eachFile) {
> ## pass the directory to the routine ( recursion )
> print "recursing $eachFile\n";
> recurse($eachFile, $days);
> } else {
>
> ## print the file ... tabbed for readability
> my $now = time;
> my @stat = stat("$eachFile");
> if ($stat[9] < ($now - $seconds))
> {
> #print "del $eachFile\n";
> print MYFILE "del \"$eachFile\"\n";
> unlink("$eachFile");
> print "Done.\n";
> } print "\t",$eachFile,"\n";
> }
> }
>

OK, you should definitely use opendir instead of glob, next time because it's
safer. However, in your case you should use File::Find or a similar module
(see http://perl-begin.org/uses/sys-admin/#directory_traversal ) or maybe
File::Path's rmtree() function.

Your code is not going to remove the directories themselves.

Regards,

Shlomi Fish.

--
------------------------------------------------------------ -----
Shlomi Fish http://www.shlomifish.org/
Original Riddles - http://www.shlomifish.org/puzzles/

Larry Wall applies a patch manually quicker than GNU patch.

Please reply to list if it's a mailing list post - http://shlom.in/reply .

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: (unintialized value in number lt (<) at) error

am 02.08.2011 20:58:51 von Brandon McCaig

On Tue, Aug 2, 2011 at 1:12 PM, Shlomi Fish wrote:
> If you were going to get rid of the prototype (which is not a good idea - see
> the above link) please don't comment-out the original line because it just
> introduces clutter.

Just to nitpick, the wording here is misleading. It sounds like Shlomi
Fish said that getting rid of the prototype was a bad idea. :) I think
we all know that he meant that using prototypes is not a good idea,
but the OP might not. :) So to reiterate, subroutine prototypes are
considered unnecessary and bad when used without reason.


--
Brandon McCaig
V zrna gur orfg jvgu jung V fnl. Vg qbrfa'g nyjnlf fbhaq gung jnl.
Castopulence Software

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/