shein@ferdowsi.berkeley.edu (Soren Hein) (05/29/91)
The below script, 'profil', is intended to print some statistics on user accounts. It recursively goes through the directory tree from the invocation point, and records file sizes along with last access date. It is heavily based on an example from the Scriptures. 'Profil' is my first perl script, and is therefore written for its educational value rather than its usefulness. I post it for two reasons: 1. To hopefully get some hints on how to think Perl. 2. To ask what statistics on accounts would really be useful to know. (I'm a mere mortal, not a sysadmin. Hence also the warn's rather than die's.) /Soren ------ Sample output: Days files %files M avg.K %compr. 1 504 11.88 1.196 2.37 0.00 2 3 0.07 0.217 72.29 0.00 3 2 0.05 0.015 7.46 0.00 7 369 8.69 1.938 5.25 18.26 14 313 7.38 3.898 12.45 12.89 21 178 4.19 1.000 5.62 31.92 30 490 11.55 1.687 3.44 60.87 60 350 8.25 2.608 7.45 16.88 90 1821 42.91 7.299 4.01 23.08 120 25 0.59 0.120 4.78 100.00 150 35 0.82 0.177 5.05 100.00 180 1 0.02 0.004 3.65 100.00 270 141 3.32 0.483 3.42 100.00 360 12 0.28 0.259 21.59 100.00 ---------------------------------------------------------------------- 4244 100.00 20.900 4.92 25.69 --------- #!/usr/local/bin/perl # Soren Hein, shein@robotics.berkeley.edu, 05/28/91. # Rudimentary account statistics program. Recursive part adapted from # the Book, p. 56f. Works with 4.003 at least. require "pwd.pl"; # Initialize. @daylimits = (1, 2, 3, 7,14,21,30,60,90,120,150,180,270,360,100000); @numfiles = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @sizes = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @compr = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); &initpwd; # Start at the top. &dodir('.'); # Add up some totals. $totf = $totsiz = $totcom = 0; for ($i = 0; $i <= $#numfiles; ++$i) { $totf += $numfiles[$i]; $totsiz += $sizes[$i]; $totcom += $compr[$i]; } # Print out summary. print "Days files %files M", " avg.K %compr.\n"; for ($i = 0; $i <= $#numfiles; ++$i) { printf "%3d %5d %10.2f %8.3f %10.2f %10.2f\n", $daylimits[$i], $numfiles[$i], 100 * $numfiles[$i] / $totf, $sizes[$i] / ( 1000 * 1000 ) , $sizes[$i]/( 1000 * $numfiles[$i] ), 100 * $compr[$i] / $sizes[$i] unless (($numfiles[$i] == 0) || $sizes[$i] == 0 || $totf == 0); } print "---------------------------------------", "-------------------------------\n"; printf " %5d %10.2f %8.3f %10.2f %10.2f\n", $totf, 100.00, $totsiz / (1000*1000), $totsiz / (1000 * $totf), 100 * $totcom / $totsiz; sub dodir { # Get arguments. local($dir, $nlink) = @_; # Declare local variables. local($dev, $ino, $mode, $subcount); # At the top level, we need to find nlink ourselves. ($dev, $ino, $mode, $nlink) = stat('.') unless $nlink; # Get the list of files in the current directory. if ( !(opendir(DIR, '.')) ) { warn "Can't open $dir."; } else { local(@filenames) = readdir(DIR); closedir(DIR); if ($nlink == 2) { # This directory has no subdirectories. for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; $name = $_; # Count everything but symbolic links. if (!(-l $name)) { ®ister($name); } } } else { # This directory has subdirectories. $subcount = $nlink - 2; for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; $name = "$_"; # Count everything but symbolic links. if (!(-l $name)) { ®ister($name); } next if $subcount == 0; # Seen all the subdirectories? # Get link count and check for directoriness. ($dev, $ino, $mode, $nlink) = lstat($_); next unless -d _; # It really is a directory, so do it recursively. if ( !(&chdir($_)) ) { warn "Can't cd to $name"; } else { &dodir($name, $nlink); &chdir('..'); } --$subcount; } } } } sub register { local($name) = @_; local($acctime) = -A $name; local($i) = 0; # Find time slot. while ($acctime > $daylimits[$i]) { ++$i; } ++$numfiles[$i]; $size = -s $name; $sizes[$i] += $size; # Is the file compressed? if ($name =~ m/(\w+)*\.Z$/) { $compr[$i] += $size; } }