Task

Beginning from the current directory, or optionally from a directory specified as a command-line argument, determine how many files there are of various sizes in a directory hierarchy.



My suggestion is to sort by logarithmn of file size, since a few bytes here or there, or even a factor of two or three, may not be that significant.

Don't forget that empty files may exist, to serve as a marker.



Is your file system predominantly devoted to a large number of smaller files, or a smaller number of huge files?




INCLUDE "D2:PRINTF.ACT" ;from the Action! Tool Kit
 
PROC SizeDistribution(CHAR ARRAY filter INT ARRAY limits,counts BYTE count)
  CHAR ARRAY line(255),tmp(4)
  INT size
  BYTE i,dev=[1]
 
  FOR i=0 TO count-1
  DO
    counts(i)=0
  OD
 
  Close(dev)
  Open(dev,filter,6)
  DO
    InputSD(dev,line)
    IF line(0)=0 THEN
      EXIT
    FI
    SCopyS(tmp,line,line(0)-3,line(0))
    size=ValI(tmp)
    FOR i=0 TO count-1
    DO
      IF size<limits(i) THEN
        counts(i)==+1
        EXIT
      FI
    OD
  OD
  Close(dev)
RETURN
 
PROC GenerateLimits(INT ARRAY limits BYTE count)
  BYTE i
  INT l
 
  l=1
  FOR i=0 TO count-1
  DO
    limits(i)=l
    l==LSH 1
    IF l>1000 THEN l=1000 FI
  OD
RETURN
 
PROC PrintBar(INT len,max,size)
  INT i,count
 
  count=4*len*size/max
  IF count=0 AND len>0 THEN
    count=1
  FI
  FOR i=0 TO count/4-1
  DO
    Put(160)
  OD
  i=count MOD 4
  IF i=1 THEN Put(22)
  ELSEIF i=2 THEN Put(25)
  ELSEIF i=3 THEN Put(130) FI
RETURN
 
PROC PrintResult(CHAR ARRAY filter
  INT ARRAY limits,counts BYTE count)
 
  BYTE i
  CHAR ARRAY tmp(5)
  INT min,max,total
 
  total=0 max=0
  FOR i=0 TO count-1
  DO
    total==+counts(i)
    IF counts(i)>max THEN
      max=counts(i)
    FI
  OD
  PrintF("File size distribution of ""%S"" in sectors:%E",filter) PutE()
  PrintE("From  To Count Perc")
  min=0
  FOR i=0 TO count-1
  DO
    StrI(min,tmp) PrintF("%4S ",tmp)
    StrI(limits(i)-1,tmp) PrintF("%3S   ",tmp)
    StrI(counts(i),tmp) PrintF("%3S ",tmp)
    StrI(counts(i)*100/total,tmp) PrintF("%3S%% ",tmp)
    PrintBar(counts(i),max,17) PutE()
    min=limits(i)
  OD
RETURN
 
PROC Main()
  DEFINE LIMITCOUNT="11"
  CHAR ARRAY filter="H1:*.*"
  INT ARRAY limits(LIMITCOUNT),counts(LIMITCOUNT)
 
  Put(125) PutE() ;clear the screen
  GenerateLimits(limits,LIMITCOUNT)
  SizeDistribution(filter,limits,counts,LIMITCOUNT)
  PrintResult(filter,limits,counts,LIMITCOUNT)
RETURN