Forum Moderators: coopster & phranque

Message Too Old, No Replies

directory size in ftp

directory size from within a ftp session

         

bigshow

7:12 am on Sep 27, 2005 (gmt 0)

10+ Year Member



I'm running a perl script from a unix server and ftp'ing to a windows server (it could be Windows 2000 or Windows 2003 server).
I need to get the size of a folder (including all it's sub-folders).

I've tried:

use Net::FTP;
my $username=xyz;
my $password=abcd;
my $directory='\temp';

$ftp = Net::FTP->new("servername") or die "Can't connect: $@\n";
$ftp->login($username, $password) or die "Couldn't login\n";
$dir_size=$ftp->size($directory) or die "Couldn't get directory size\n";
$ftp->quit() or warn "Couldn't quit.\n";
print "Size: $dir_size\n";

But it fails at the "Couldn't get directory size".

However, it works if i try size on a file: $file_size=$ftp->size($filename) or die "Couldn't get $filename size\n";

The man page for Net::FTP indicates you can only do a $ftp->size($filename) on a file not a directory.

I need to be able to get the directory size - any idea's how?

KevinADC

8:34 am on Sep 27, 2005 (gmt 0)

10+ Year Member



run this script and then post some of the lines from the printout so I can see how your server returns a dir() listing.

#!/usr/bin/perl -w
use CGI qw/:standard/;
use strict;
use Net::FTP;
print header,start_html;

my $username='xyz';
my $password='abcd';
my $directory='\temp';

my $ftp = Net::FTP->new("servername") or die "Can't connect: $@\n";
$ftp->login($username, $password) or die "Couldn't login\n";
$ftp->cwd($directory) or die "$!";
my @list = $ftp->dir($directory) or die "$!";
for (@list) {
print "$_<br>\n";
}
$ftp->quit() or warn "Couldn't quit.\n";
print end_html;

bigshow

10:45 am on Sep 27, 2005 (gmt 0)

10+ Year Member



Here's the output from running the code - i changed \temp to the actual folder i'm interested in....

Content-Type: text/html; charset=ISO-8859-1

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head><title>Untitled Document</title>
</head><body>01-25-03 12:32PM <DIR> Acs32<br>
09-14-04 01:03AM <DIR> Archive<br>
09-27-05 01:08AM <DIR> asset_export<br>
07-05-05 08:16PM <DIR> ats_ye<br>
06-28-05 03:02PM <DIR> ats32<br>
06-08-04 08:50PM 961 atscopy.bat<br>
07-03-03 01:40PM <DIR> atseod<br>
08-05-04 04:52PM <DIR> cp_export<br>
09-27-05 11:40AM <DIR> data<br>
01-25-03 12:29PM <DIR> DDICT<br>
11-22-04 07:41PM <DIR> DOWNLOAD<br>
04-05-04 09:01AM <DIR> emcc_download<br>
08-12-02 05:39PM 40960 eu.dll<br>
09-27-05 08:45AM <DIR> EURO<br>
01-13-05 04:48PM <DIR> exis<br>
09-27-05 10:07AM <DIR> FAX<br>
06-08-04 08:49PM <DIR> fees<br>
06-02-05 08:18PM <DIR> FOXPRO25<br>
09-16-05 07:10PM <DIR> from_atlas<br>
05-26-05 03:46PM <DIR> imports<br>
02-23-05 06:04PM <DIR> install<br>
09-26-05 11:28PM <DIR> Logs<br>
01-25-03 01:08PM <DIR> posrec<br>
09-23-05 12:30AM <DIR> ps<br>
01-25-03 01:09PM <DIR> QUANTIX<br>
05-05-05 02:25PM <DIR> Replication Test<br>
09-27-05 10:57AM <DIR> REPORT<br>
01-25-03 01:10PM <DIR> Results<br>
01-25-03 01:10PM <DIR> SETUP32<br>
07-25-05 11:55AM <DIR> SIGNOFF<br>
09-27-05 04:30AM <DIR> TEMP<br>
09-27-05 04:30AM <DIR> trax<br>
07-27-04 05:06PM <DIR> Vis_sp6<br>
07-27-04 05:54PM <DIR> VISION32<br>
</body></html>$

You'll see files supply a size, but not folders.

KevinADC

5:41 pm on Sep 27, 2005 (gmt 0)

10+ Year Member



I can't test this, and you will need to verify that the total file size being returned is accurate before trusting the script (if it works):



use Net::FTP;
my $username=xyz;
my $password=abcd;
my $directory='\temp';
my $ftp = Net::FTP->new("servername") or die "Can't connect: $@\n";
$ftp->login($username, $password) or die "Couldn't login\n";
my $total_size = '0';
$total_size = get_space($directory);
sub get_space {
local $_ = shift;
#print "<b>$_</b><br>";
$ftp->cwd($_) or die "can't change to directory '$_': $!";
my @list = $ftp->dir($_) or next;
foreach my $line (@list) {
my @f = split(/\s+/,$line);
if (index($line,'<DIR>') > -1) {get_space("$_/$f[-1]")}
else {$total_size += $ftp->size($f[-1])}
}
return($total_size);
}
$ftp->quit() or warn "Couldn't quit.\n";
print "Total Size: $total_size\n";
print end_html;

bigshow

1:51 pm on Sep 28, 2005 (gmt 0)

10+ Year Member



Great, this is almost there....

I get:
can't change to directory '/atslive/logs/Logs': at ./4.pl line 18.

when the Windows directory has a space in it's name,e.g. the path is /atslive/logs/2004 Logs

The script is dropping the 2004 bit from the folder name.

Any further suggestions?

Thanks

KevinADC

7:05 pm on Sep 28, 2005 (gmt 0)

10+ Year Member



the problem is when the lines are split on the spaces, say you have this line:

05-05-05 02:25PM <DIR> Replication Test

the line is split into an array which contains:

05-05-05
02:25PM
<DIR>
Replication
Test

the last element of the array is used as the foldername or filename, in this case only "Test" would get used and the cwd() function would fail if there is no folder named "Test". I failed to notice that this condition could exist. Normally spaces in names for internet files/folders is a no-no. I'll see what I can come up with though.

KevinADC

7:52 pm on Sep 28, 2005 (gmt 0)

10+ Year Member



Hopefully this solved the problem. It does assume that there is only one space after <DIR> in the lines returned by the $ftp->dir() function.



#!perl
use CGI qw/:standard/;
use strict;
use Net::FTP;
print header;
my $username='xyz';
my $password='abcd';
my $directory='\temp';
my $ftp = Net::FTP->new("servername") or die "Can't connect: $@\n";
$ftp->login($username, $password) or die "Couldn't login\n";
my $total_size = '0';
$total_size = get_space($directory);
sub get_space {
local $_ = shift;
#print "<b>$_</b><br>";
$ftp->cwd($_) or die "can't change to directory '$_': $!";
my @list = $ftp->dir($_) or next;
foreach my $line (@list) {
chomp $line;
if (index($line,'<DIR>') > -1) {
my $name = substr $line,index($line,'<DIR>')+6;
#print " $name<br>\n";
get_space("$_/$name");
}
else {
my $name = (split(/\s+/,$line))[-1];
#print " $name<br>\n";
$total_size += $ftp->size($name);
}
}
return($total_size);
}
$ftp->quit() or warn "Couldn't quit.\n";
print "Total Size: $total_size\n";
print end_html;

the problem with this script is that it is not portable at all. It will only work on a server that returns a list formatted like yours, with <DIR> followed by the folder name. My ftp server returns a differently formatted string, like this:

drwxr-xr-x 2 e-pixsco e-pixsco 4096 Jun 22 2003 bryce4
drwxr-xr-x 3 e-pixsco e-pixsco 4096 Sep 25 15:53 cgi-bin
-rw-r--r-- 1 e-pixsco e-pixsco 7472 Mar 23 2003 colors.html
-rw-r--r-- 1 e-pixsco e-pixsco 18524 Mar 23 2003 colors2.html

so if you hope to use this script on more than one server it may not work.

I also wish this forum formatted code better. hint-hint to the admins :)

coopster

9:19 pm on Sep 28, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



mods/admins have no control over any of the code nor files ... that privilege belongs to the site owner.

However, you can format code somewhat. Anytime you are creating or replying to a message you will notice a link to the left of the dialog box that tells you that Style Codes [webmasterworld.com] are on. I use the [pre] tags most often, but you have to make sure you don't have blank lines in between your lines anywhere and that your lines don't extend too far (wrap) as they are not going to wrap ... simply make the sidescroll widen out on your post.

KevinADC

9:35 pm on Sep 28, 2005 (gmt 0)

10+ Year Member



thanks coopster for the tip. Thats what I am already doing, using the pre style tags. I just wish indentation was preserved a bit better. I know the site owners/admins/mods don't want the display too messed up with long lines of unwrapped text, I have had a post edited before because of this and it was explained to me why.

The code style tags are almost useless, just seems to change the font style but not preserve any formatting at all. Oh well, can't have everything!