Task: File size distribution




Go: package main

import (
    "fmt"
    "log"
    "math"
    "os"
    "path/filepath"
)

func commatize(n int64) string {
    s := fmt.Sprintf("%d", n)
    if n < 0 {
        s = s[1:]
    }
    le := len(s)
    for i := le - 3; i >= 1; i -= 3 {
        s = s[0:i] + "," + s[i:]
    }
    if n >= 0 {
        return s
    }
    return "-" + s
}

func fileSizeDistribution(root string) {
    var sizes [12]int
    files := 0
    directories := 0
    totalSize := int64(0)
    walkFunc := func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        files++
        if info.IsDir() {
            directories++
        }
        size := info.Size()
        if size == 0 {
            sizes[0]++
            return nil
        }
        totalSize += size
        logSize := math.Log10(float64(size))
        index := int(math.Floor(logSize))
        sizes[index+1]++
        return nil
    }
    err := filepath.Walk(root, walkFunc)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("File size distribution for '%s' :-\n\n", root)
    for i := 0; i < len(sizes); i++ {
        if i == 0 {
            fmt.Print("  ")
        } else {
            fmt.Print("+ ")
        }
        fmt.Printf("Files less than 10 ^ %-2d bytes : %5d\n", i, sizes[i])
    }
    fmt.Println("                                  -----")
    fmt.Printf("= Total number of files         : %5d\n", files)
    fmt.Printf("  including directories         : %5d\n", directories)
    c := commatize(totalSize)
    fmt.Println("\n  Total size of files           :", c, "bytes")
}

func main() {
    fileSizeDistribution("./")
}








Ada: with Ada.Numerics.Elementary_Functions;
with Ada.Directories;    use Ada.Directories;
with Ada.Strings.Fixed;  use Ada.Strings;
with Ada.Command_Line;   use Ada.Command_Line;
with Ada.Text_IO;        use Ada.Text_IO;

with Dir_Iterators.Recursive;

procedure File_Size_Distribution is

   type Exponent_Type is range 0 .. 18;
   type File_Count    is range 0 .. Long_Integer'Last;
   Counts         : array (Exponent_Type) of File_Count := (others => 0);
   Non_Zero_Index : Exponent_Type   := 0;
   Directory_Name : constant String := (if Argument_Count = 0
                                        then "."
                                        else Argument (1));
   Directory_Walker : Dir_Iterators.Recursive.Recursive_Dir_Walk
     := Dir_Iterators.Recursive.Walk (Directory_Name);
begin
   if not Exists (Directory_Name) or else Kind (Directory_Name) /= Directory then
      Put_Line ("Directory does not exist");
      return;
   end if;

   for Directory_Entry of Directory_Walker loop
      declare
         use Ada.Numerics.Elementary_Functions;
         Size_Of_File : File_Size;
         Exponent     : Exponent_Type;
      begin
         if Kind (Directory_Entry) = Ordinary_File then
            Size_Of_File := Size (Directory_Entry);
            if Size_Of_File = 0 then
               Counts (0) := Counts (0) + 1;
            else
               Exponent := Exponent_Type (Float'Ceiling (Log (Float (Size_Of_File),
                                                              Base => 10.0)));
               Counts (Exponent) := Counts (Exponent) + 1;
            end if;
         end if;
      end;
   end loop;

   for I in reverse Counts'Range loop
      if Counts (I) /= 0 then
         Non_Zero_Index := I;
         exit;
      end if;
   end loop;

   for I in Counts'First .. Non_Zero_Index loop
      Put ("Less than 10**");
      Put (Fixed.Trim (Exponent_Type'Image (I), Side => Left));
      Put (": ");
      Put (File_Count'Image (Counts (I)));
      New_Line;
   end loop;
end File_Size_Distribution;