[forwarded submission from a non-member address -- rjk]
From: Bob Rogers <[EMAIL PROTECTED]>
Date: Wed, 24 Jul 2002 09:10:25 -0400
Subject: Re: [Boston.pm] getting a directory size
To: Erik Price <[EMAIL PROTECTED]>
CC: "Steve Linberg" <[EMAIL PROTECTED]>,
"[EMAIL PROTECTED]" <[EMAIL PROTECTED]>
From: "Steve Linberg" <[EMAIL PROTECTED]>
Date: Wed, 24 Jul 2002 02:03:22 -0400 (EDT)
On Wed, 24 Jul 2002, Erik Price wrote:
> Is there a
> command or something that can recursively determine the amount of disk
> space "contained" in a directory that I can use in this pipe?
du -s -k dir_name
(du = "disk usage" on some *nixen)
But note that not all of them understand "-k"; if they don't, you
probably don't need it.
Here's a minimal script I wrote (a while ago, it seems) to do "du" by
user, back when we were having quota problems. Using a pipe would
undoubtedly be more efficient, but this should give you some ideas in
case "du" doesn't do quite what you want (or you're not using Unix).
-- Bob Rogers
http://rgrjr.dyndns.org/
#!/usr/local/bin/perl
#
# du by user. [doesn't properly account for hard links, though. -- rgr,
# 15-Jun-98.]
#
# Modification history:
#
# created. -- rgr, 15-Jun-98.
#
sub user_name {
my $uid = shift;
$uid_to_user_name{$uid}
|| ($uid_to_user_name{$uid} = getpwuid($uid));
}
sub du_dir {
my ($dir, $parent_size) = @_;
my ($file, $uid, %size, $subdir, @subdirs);
opendir(DIR, $dir) || die;
while ($file = readdir(DIR)) {
chomp($file);
next if $file eq '..'; # we don't own our parent directory.
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks)
= lstat("$dir/$file");
$size{$uid} += $blocks;
$size{'total'} += $blocks;
# print(join("\t", "$dir/$file", $size, $blocks, sprintf('%o', $mode)), "\n");
if ($mode & oct(40000) && $file ne '.') {
push(@subdirs, "$dir/$file");
}
}
closedir(DIR);
# Recur into subdirectories, in what is effectively a preorder traversal.
# Do this *after* we are through with DIR, because directory filehandles are
# globally scoped. -- rgr, 15-Jun-98.
foreach $subdir (@subdirs) {
du_dir($subdir, \%size);
}
# Report results.
$size = sprintf('%d', ($size{'total'}+1)/2);
print("$size\t$dir");
foreach $uid (sort(keys(%size))) {
$ {$parent_size}{$uid} += $size{$uid};
unless ($uid eq 'total') {
$size = sprintf('%d', ($size{$uid}+1)/2);
print("\t$size\t", user_name($uid));
}
}
print "\n";
}
push(@ARGV, '.') unless @ARGV;
%size = ();
foreach $arg (@ARGV) {
du_dir($arg, \%size)
if -d $arg;
}