CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Win32 Programming Help:
No results from using GetFileTime and getFileSize

 



gixxer05
Novice

Apr 17, 2009, 12:09 PM

Post #1 of 11 (8010 views)
No results from using GetFileTime and getFileSize Can't Post

Greetings,

Can anyone lend a hand deciphering why my code will not produce any results except for the last print statement, the sum of files and file sizes? I can't get the GetFileSize and getFileTime functions to produce any results. If you can't tell from the code, I'm trying to print a continually updated list of archived files in a directory (something like the ps process command in UNIX). I also need to figure out how to create a text file of the output (list of files within the directory) and save it to a different location at 3:57 every day. I'm still scratching my head, working with Date::Manip::parserecur(). I'll leave that question for later and focus on the present issue. Crazy Any and all Perl guru's, please take a look at my code. I exhausted all other resources and would really appreciate any help. Thanks in advance.


Code

#!perl

#!/usr/bin/perl

# Language: Perl 5.10

use warnings;



use
Date::Manip;

use time::localtime;

use Time::Local;

use Win32API::File::Time qw/GetFileTime/;

use Win32API::File qw/getFileSize/;

# Print page header

print "\n\nDirectory of C:\\reports\n\n";

$seconds = 5;

sub action;

while(1)

{

# Generate report of directory

&action;

# Sleep for 5 seconds

sleep($seconds);

}

sub action

{

# Report list directory

$dname = "C:\\reports\\";

# Open and read directory, pass directory/file location to DIR or issue error message

opendir(DIR, $dname) or die "Can't open directory $dirname: $!";

#Create an array of all files ending with .txt or .pdf in the Current Directory

@files = sort(grep(/txt|pdf$/, readdir(DIR)));

closedir(DIR);

$position = 0;

$totalfiles = 0;

$sumsizefiles = 0;

foreach (@files)

{

$position++; # Array position

$totalfiles++;

# Finding the Size in Bytes of Regular Files

#$fileSize[$position] = -s $files[$position]; # NOT WORKING

$fileSize[$position] = getFileSize($file[$position]) / 1024;

$sumsizefiles += $fileSize[$position];

# Determine the access age of the Files

#$fileAge[$position] = -A $files[$position]; # NOT WORKING

$fileAge[$position] = GetFileTime($file[$position]);

# Print array of Files, unless File is a directory

printf($file[$position], " ", $fileSize[$position], " ", $fileAge[$position], "\n") unless -d @file;

}

# Print the total files and sum of file sizes

$sumsizefiles = $sumsizefiles / 1024 ;

printf("\n", $totalfiles, "File(s) ", $sumsizefiles, " Kb\n");

}






FishMonger
Veteran / Moderator

Apr 17, 2009, 1:08 PM

Post #2 of 11 (8007 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Why aren't you using the strict pragma?

Why Are you using the Win32API modules instead of Perl's built-in stat function?

Why do you load 3 date/time modules but never use them?

Why are you using printf without specifying a format?

Array's are 0 indexed, meaning the first index is 0 not 1. "Off by 1" is the second most common mistake.


Code
printf($file[$position], " ", $fileSize[$position], " ", $fileAge[$position], "\n") unless -d @file;

@file was never defined/populated.


gixxer05
Novice

Apr 21, 2009, 5:54 AM

Post #3 of 11 (7935 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Why aren't you using the strict pragma?

I commented out strict at my last compile, before posting, to debug with warnings. I still plan on using it.

Why Are you using the Win32API modules instead of Perl's built-in stat function?


I tried using the stat functions, even POSIX, to no avail. It seems I'm getting further along by using the current method of extracting file data. However, I have only been able to produce the file name and size for output, excluding the creation time.


Why do you load 3 date/time modules but never use them?
The 3 modules are included because I reworked the code atleast 5 times, using those modules because processing must occur at timed intervals and paths/files have to be named as follows: yyyy\April\mm-dd-yyyy. Create the reports directory list, as a text file, on each Monday thru Thursday at 3:58 am, save the file to the curent day's folder. Then repeadetly list (10 second pause, daemon) the directory contents from 5 am to 3:57 am the next day. Send directory file list created between Friday 5am to Monday 3:57am to the numbered date for last Friday.

I already completed code for creating the folders for each year, month, day.

Why are you using printf without specifying a format?

A little confused on how to format my output for this output. Couldn't find anything similar on the net with mixed output, can you offer an example?

Array's are 0 indexed, meaning the first index is 0 not 1. "Off by 1" is the second most common mistake.

So should I preincrement instead of post increment? How will this make a difference since there should be a filename at 0. It should be file[0] = filename, correct? Please explain a little further.


FishMonger
Veteran / Moderator

Apr 21, 2009, 7:06 AM

Post #4 of 11 (7927 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post


In Reply To
I commented out strict at my last compile, before posting, to debug with warnings.

Those pragmas should be used together, as apposed to either/or. The strict pragma would have told you about the @files problem I mentioned.


In Reply To
I tried using the stat functions, even POSIX, to no avail. It seems I'm getting further along by using the current method of extracting file data. However, I have only been able to produce the file name and size for output, excluding the creation time.

The stat function returns a 13 element list. The 11th element is the ctime, in Windows that's the file creation timestamp.



In Reply To
Why do you load 3 date/time modules but never use them?
The 3 modules are included because I reworked the code atleast 5 times, using those modules because processing must occur at timed intervals and paths/files have to be named as follows: yyyy\April\mm-dd-yyyy.

That could easily be accomplished with the strftime function in the POSIX module.


In Reply To
Why are you using printf without specifying a format?

A little confused on how to format my output for this output. Couldn't find anything similar on the net with mixed output, can you offer an example?

Read the perldoc for both printf and sprintf.
C:\>perldoc -f printf
C:\>perldoc -f sprintf


In Reply To
Array's are 0 indexed, meaning the first index is 0 not 1. "Off by 1" is the second most common mistake.

So should I preincrement instead of post increment? How will this make a difference since there should be a filename at 0. It should be file[0] = filename, correct? Please explain a little further.

You initialized $position to 0, then at the beginning of the loop, you increment it to 1. So, the first time you access the @fileSize array, you enter it at index 1, skipping over index 0.


gixxer05
Novice

Apr 21, 2009, 10:57 AM

Post #5 of 11 (7911 views)
Re: [FishMonger] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Thanks for your replies, they've been quite helpful. I recreated the code, attempting to implement your stat and suggestions. The following code compiles without errors or warnings, but doesn't produce any output except:

Hard fail, but say why ($!): No such file or directory

I didn't have an issue accessing my directory before. What am I missing? Thanks again.


Code
 

#use warnings;

#use strict;

use File::stat;

my $seconds = 5;

$sb = stat(@files);

# MNCS Report list directory

$dname = "C:\\Reports\\";

# Open and read directory, pass directory/file location to DIR or issue error message

opendir(DIR, $dname) or die "Can't open directory $dname: $!";

# TRANSFORM TO LOWERCASE

foreach $files(@files)

{

push(@files, "\L$files");

}

#Sort, Create an array of all files ending with .txt or .pdf in the Current Directory

my @files = sort(grep(/txt|pdf$/, readdir(DIR)))or die "Hard fail, but say why (\$!): $!\n";

closedir(DIR);

while (DIR)

{

# begin report of MNCS directory

foreach $files (@files)

{

printf "%s, %s\n", @files[position], $sb->size, scalar localtime $sb->mtime;

$sumsizefiles += $sb->size;

++$totalfiles;

++$position;

}

# Print the total files and sum of file sizes

$sumsizefiles = $sumsizefiles / 1024;

printf("\n", $totalfiles, "File(s) ", $sumsizefiles, " Kb\n");

$position = 0;

$totalfiles = 0;

$sumsizefiles = 0;

# Sleep for 5 seconds

sleep($seconds);

}




FishMonger
Veteran / Moderator

Apr 21, 2009, 11:07 AM

Post #6 of 11 (7908 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post


Quote
The following code compiles without errors or warnings

That's only because you told Perl not to tell you about the problems!

Enable the strict warnings pragmas (i.e., uncomment those lines) and you'll get a number of warnings and errors.


gixxer05
Novice

Apr 21, 2009, 12:48 PM

Post #7 of 11 (7902 views)
Re: [FishMonger] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Thanks...didn't realize! Crazy I refined the code again and discovered a few errors in my code. However, can you explain the following error? Explicit package?

I'm still getting errors: Global symbol "$files" requires explicit package

For the following modified code:


Code
 

use warnings;

use strict;

use File::stat;

my $position = 0;

my $seconds = 5;

my @files;

my $dname;

my $sb = stat(@files);

my $totalfiles = 0;

my $sumsizefiles = 0;

my $DIRECT;

# MNCS Report list directory

$dname = "C:\\Reports\\";

# Open and read directory, pass directory/file location to DIR or issue error message

opendir($DIRECT, $dname) or die "Can't open directory $dname: $!";

# TRANSFORM TO LOWERCASE

foreach $files(@files)

{

push(@files, "\L$files");

}

#Sort, Create an array of all files ending with .txt or .pdf in the Current Directory

@files = sort(grep(/txt|pdf$/, readdir($DIRECT)))or die "Hard fail, but say why (\$!): $!\n";

closedir($DIRECT);

while ($DIRECT)

{

# begin report of MNCS directory

foreach $files (@files)

{

printf "%s, %s\n", $files[$position], $sb->size, scalar localtime $sb->mtime;

$sumsizefiles += $sb->size;

++$totalfiles;

++$position;

}

# Print the total files and sum of file sizes

$sumsizefiles = $sumsizefiles / 1024;

printf "%3.0d, %8.0f\n", $totalfiles, "File(s) ", $sumsizefiles, " Kb\n";

$position = 0;

$totalfiles = 0;

$sumsizefiles = 0;

# Sleep for 5 seconds

sleep($seconds);

}







FishMonger
Veteran / Moderator

Apr 21, 2009, 1:05 PM

Post #8 of 11 (7899 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post


Quote
I'm still getting errors: Global symbol "$files" requires explicit package

The complete error message includes the line number of the problem. Did you look at that line?

It's comming from:

Code
foreach $files(@files)

which should be:

Code
foreach my $files(@files)


This line has 2 problems.

Code
my $sb = stat(@files);

1) @files is undefined.
2) the stat function operates on a single file, not an array.

There are a number of other problems, but start by fixing those and then see what happens.


gixxer05
Novice

Apr 27, 2009, 8:59 AM

Post #9 of 11 (7724 views)
Re: [FishMonger] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Good afternoon,

I made your suggested revisions to the code. Thanks. However, I still don't get the proper output. After revisements, the following code produces only directory information. I need all underlying files within the directory showing size and time. What's wrong with my code? I have yet to produce size and time data for each file outside of using system(dir).


Code
 

use warnings;

use strict;

use File::stat;

my $position = 0;

my $seconds = 5;

my @files = qw/0/;

my $files;

my $dname;

my $sb;

my ($size, $mtime);

my $totalfiles = 0;

my $sumsizefiles = 0;

my $DIRECT;

# MNCS Report list directory

$dname = "C:\\Reports\\";

# Open and read directory, pass directory/file location to DIR or issue error message

opendir($DIRECT, $dname) or die "Can't open directory $dname: $!";

#Sort, Create an array of all files ending with .txt or .pdf in the Current Directory

@files = readdir($DIRECT) or die "Hard fail, but say why (\$!): $!\n";

closedir($DIRECT);

while (1)

{

# begin report of MNCS directory

foreach my $file (@files)

{

my $staticfileinfo = $files[$position];

$sb = stat($staticfileinfo);

printf "%s %8.0f %s \n", $staticfileinfo, $sb->size, scalar localtime $sb->mtime;

$sumsizefiles += $sb->size;

++$totalfiles;

++$position;

}

# Print the total files and sum of file sizes

$sumsizefiles = $sumsizefiles / 1024;

printf "\n%3.0d %s %8.0f %s\n", $totalfiles, "File(s) ", $sumsizefiles, " Kb\n";

$position = 0;

$totalfiles = 0;

$sumsizefiles = 0;

# Sleep for 5 seconds

sleep($seconds);



}

. 0 Wed Apr 22 09:35:47 2009

.. 0 Wed Apr 1 13:21:41 2009



Can't call method "size" on an undefined value at
C:/~/workspace/mnindex/mnindex6.pl line 42.


FishMonger
Veteran / Moderator

Apr 27, 2009, 10:48 AM

Post #10 of 11 (7712 views)
Re: [gixxer05] No results from using GetFileTime and getFileSize [In reply to] Can't Post

You should always use the full path when doing the stat and you should declare your vars in the smallest scope that they need.

In almost all cases, it's better to use forward slashes in paths rather than backslashes.

Please use proper indentation. Your complete lack of indentation makes your code difficult to read/follow.

Try this cleaned up version.

Code
#!/usr/bin/perl 

use warnings;
use strict;
use File::stat;

while(1) {

my $subdirs;
my $totalfiles;
my $sumsizefiles;
my $dname = "C:/Reports";

opendir(my $DIRECT, $dname) or die "Can't open directory $dname: $!";

while ( my $file = readdir($DIRECT) ) {
$file = "$dname/$file";
$subdirs++ and next if -d $file;
$totalfiles++;
my $sb = stat($file);
$sumsizefiles += $sb->size;
printf "%s %8.0f %s \n", $file, $sb->size, scalar localtime $sb->mtime;
}

closedir($DIRECT);

# Print the total files and sum of file sizes
printf "\n%3d File(s) %d KB\n", $totalfiles, $sumsizefiles/1024;
print "Not including $subdirs Sub Directories\n";

sleep 5;
}


You may want to take a look at these modules.

File::Monitor - Monitor files and directories for changes.
http://search.cpan.org/~andya/File-Monitor-0.10/lib/File/Monitor.pm

Win32::FileSystem::Watcher - Watch a Win32 file system for changes (asynchronously).
http://search.cpan.org/~ank/Win32-FileSystem-Watcher-0.1.0/lib/Win32/FileSystem/Watcher.pm


(This post was edited by FishMonger on Apr 27, 2009, 10:49 AM)


gixxer05
Novice

Apr 27, 2009, 11:55 AM

Post #11 of 11 (7708 views)
Re: [FishMonger] No results from using GetFileTime and getFileSize [In reply to] Can't Post

Ah! Smile Thanks! Interesting how you passed the path/filename to stat(). Also, can you provide tip or two when scoping variables. I'm impressed that the code didn't flag for uninitialized globals. I guess because you encapsulated the variables by declaring them within their respective blocks. Would declaring global variables cured my problems also, are there some circumstances where I should? (I know that practice is taboo in the world of Perl, but just wondering) Thanks.

JM

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives