Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!bbn!bbn.com!clements From: clements@bbn.com (Bob Clements) Newsgroups: comp.lang.perl Subject: Useful "du" (was Re: How about building in directory-tree-walking?) Message-ID: <54235@bbn.COM> Date: 29 Mar 90 15:31:22 GMT References: <39362@iuvax.cs.indiana.edu> <7514@jpl-devvax.JPL.NASA.GOV> Sender: news@bbn.COM Reply-To: clements@BBN.COM (Bob Clements) Lines: 82 In article <7514@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: >On the other hand, you can just mutate the following into what you want. > [...] >Larry > >sub dodir { > ... >} Thanks, Larry. I mutated it into the attached "useful du" which I called "used". It looks down a directory tree and prints out (almost) what "du" prints, but filters it into useful info. You tell it a depth and a size. It prints out all directories to the given depth and then anything below that level if it is as big as the given size. Basically it tells me "Where the heck has all the space gone on u0?". Usage: used /nfs/whizbang/u0 1 2000 gives you the top level of directories in u0 (even if they're not big) and all the directories lower than that that are eating more than 2 megabytes. It's my first perl program - be gentle :-) It doesn't deal with hard links, they'll be multiple-counted. Bob Clements, K1BC, clements@bbn.com ----------------------------------------------slash/chop here #!/usr/bin/perl ( $#ARGV != 2 ) && die "Usage: $0 \n" ; $srcdir = shift ; $printdepth = shift ; $thresh = shift ; $curdepth = 0; chdir($srcdir) || die "Can't chdir to $srcdir" ; $topn = &dodir($srcdir); print "Total space allocated at and below $srcdir is $topn K.\n"; sub dodir { local($intn,$belown) = 0; local($dir) = @_; local($name,$dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size); local($atime,$mtime,$ctime,$blksize,$blocks); if (opendir(DIR,'.')) { local(@filenames) = sort readdir(DIR); closedir(DIR); for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = lstat($_); next if ($mode & 0170000) eq 0120000; # don't follow symlinks $name = "$dir/$_"; $intn += $blocks/2; # report 1K blocks, not 512 byte blocks if (($mode & 0170000) == 0040000) { if (chdir $_) { $curdepth++; $belown = &dodir($name); $intn += $belown; if (($curdepth <= $printdepth) || ($belown >= $thresh)) { print "$belown\t$name\n"; } $curdepth--; chdir '..'; } else { print "*** Can't cd to $name\n"; } } } } else { print "*** Can't open $dir\n"; } $intn; } ----------------------------------------------slash/chop here