perl file size calculation not working

2020-03-07 04:41发布

问题:

I am trying to write a simple perl script that will iterate through the regular files in a directory and calculate the total size of all the files put together. However, I am not able to get the actual size of the file, and I can't figure out why. Here is the relevant portion of the code. I put in print statements for debugging:

$totalsize = 0;
while ($_ = readdir (DH)) {
   print "current file is: $_\t";
   $cursize = -s $_;           
   print "size is: $cursize\n";
   $totalsize += $cursize;
}  

This is the output I get:

current file is: test.pl    size is: 
current file is: prob12.pl  size is: 
current file is: prob13.pl  size is: 
current file is: prob14.pl  size is: 
current file is: prob15.pl  size is: 

So the file size remains blank. I tried using $cursize = $_ instead but the only effect of that was to retrieve the file sizes for the current and parent directories as 4096 bytes each; it still didn't get any of the actual file sizes for the regular files.

I have looked online and through a couple of books I have on perl, and it seems that perl isn't able to get the file sizes because the script can't read the files. I tested this by putting in an if statement:

print "Cannot read file $_\n" if (! -r _);

Sure enough for each file I got the error saying that the file could not be read. I do not understand why this is happening. The directory that has the files in question is a subdirectory of my home directory, and I am running the script as myself from another subdirectory in my home directory. I have read permissions to all the relevant files. I tried changing the mode on the files to 755 (from the previous 711), but I still got the Cannot read file output for each file.

I do not understand what's going on. Either I am mixed up about how permissions work when running a perl script, or I am mixed up about the proper way to use -s _. I appreciate your guidance. Thanks!

回答1:

If it isn't just your typo -s _ instead of the correct -s $_ then please remember that readdir returns file names relative to the directory you've opened with opendir. The proper way would be something like

my $base_dir = '/path/to/somewhere';
opendir DH, $base_dir or die;
while ($_ = readdir DH) {
  print "size of $_: " . (-s "$base_dir/$_") . "\n";
}
closedir DH;

You could also take a look at the core module IO::Dir which offers a tie way of accessing both the file names and the attributes in a simpler manner.



回答2:

You have a typo:

$cursize = -s _;

Should be:

$cursize = -s $_;