Sizes Sample
Blind Watch Maker 1
Find Words
Fractal Benchmark
Genetic Algorithm
Gtk Source Editor
Hex Dump
Simple English Parser
Word Count

The most effective technique to free up disk space on a drive is to look in the
directories that consume the most space. You may find entire directories that
can be deleted or excessively large files that are no longer needed. The first
time you do this, you might downsize the space consumed by a large factor with
only a few minutes of effort. Credit goes to the old "Dark Forest" application
on the old NeXTstep platform for introducing me to this approach.

This command line utility scans the current directory and its files for their
sizes, including all subdirectories. It then reports the total size and shows
the largest directories and files first. You can use this report to look for
large things to delete and rerun it as you progress. To run:

> cd \to\path\of\interest
> cobra \path\to\sizes.cobra

Unix users get a similar result with something like "du -k | sort -nr"

As an example, I ran `sizes` on a directory and it reported:

203658 directories and files read
180.30 seconds to read
21,297.34 MB

After spending 20 minutes cleaning up the biggest directories and files
that it listed, it then reported this:

186345 directories and files read
49.95 seconds to read
8,809.15 MB

class FileNode implements IComparable
    One of these will be created for every directory and file, and put into a
    list that can be sorted.

        a = FileNode('a', 100)
        assert a.pathName == 'a'
        assert a.numBytes == 100
        assert a.compareTo(nil) == 1
        b = FileNode('b', 200)
        assert a.compareTo(b) < 0
        assert b.compareTo(a) > 0
        c = FileNode('c', 100)
        assert a.compareTo(c) == 0

    var _pathName as String
    var _numBytes as decimal

    cue init(pathName as String, numBytes as decimal)
        _pathName = pathName
        _numBytes = numBytes

    get pathName from _pathName

    get numBytes from _numBytes

    def compareTo(obj as Object?) as int
            obj is nil  or  obj inherits FileNode
            if obj is nil
                return 1
            else if obj inherits FileNode
                return _numBytes.compareTo(obj.numBytes)
                throw FallThroughException(obj)

class Dir
    Dir does the work of scanning the files and subdirectories.
    This results in a tree-like structure that matches the file system.

        var _sep    as char   # Path.directorySeparatorChar

    var _di         as DirectoryInfo
    var _dir        as Dir?  # parent directory
    var _baseName   as String
    var _pathName   as String

    var _files      as List<of FileInfo>
    var _subdirs    as List<of Dir>

    var _count      as int
    var _numBytes   as decimal  # using 'decimal' because FileInfo.length returns int64

    cue init(pathName as String)
        """ Creates a Dir from a filesystem path string. Scans all subdirs. """
        _di = DirectoryInfo(pathName)
        _pathName = pathName
        _baseName = pathName

    cue init(di as DirectoryInfo, parentDir as Dir)
        """ Creates a Dir from a parent Dir. Scans all subdirs. """
        _di = di
        _baseName =
        _pathName = di.fullName

    get count from _count

    get numBytes from _numBytes

    def _init(parentDir as Dir?)
        assert _baseName.length
        _sep = Path.directorySeparatorChar
        _dir = parentDir
        if _dir, _pathName = '[_dir._pathName][_sep][_baseName]'
        _files = List<of FileInfo>()
        _subdirs = List<of Dir>()

    def scan
        assert _pathName.length

            dirInfo = DirectoryInfo(_pathName)
        catch IOException
            print 'warning: Unreadable directory:', _pathName

            files = dirInfo.getFiles
        catch IOException
            print 'warning: Unreadable files in directory:', _pathName

        for fi in files
                _count += 1
                _numBytes += fi.length to decimal
            catch IOException
                print 'warning: Cannot scan file:', fi.fullName

        for di in dirInfo.getDirectories
            d = Dir(di, this)
            _count += d.count
            _numBytes += d.numBytes
    get toList as List<of FileNode>
        Returns a flat list containing self, all files and all subdirs (recursively).
        t = List<of FileNode>()
        return t

    def populateList(t as List<of FileNode>) is protected
            t.count > old t.count
            t.add(FileNode(_pathName, _numBytes))
            for fi in _files
                    t.add(FileNode(fi.fullName, fi.length))
                catch IOException
                    print 'warning: Cannot scan file:', fi.fullName
            for subdir in _subdirs

class Sizes

        assert _topPercent > 0.0 and _topPercent <= 1.0
        assert _divisor > 0.0
        assert _minSize >= 0.0

        var _topPercent = 0.1
        var _divisor = 1024 * 1024.0  # megabyte
        var _minSize = 1.0  # expressed in terms of _divisor
        var _divisorLabel = 'MB'

        def main
            print 'Scanning...'
            start =
            args = CobraCore.commandLineArgs
            dirName = if(args.count > 1, args[1], Directory.getCurrentDirectory)
            topDir = Dir(dirName)
            duration =
            print '[topDir.count] directories and files read'
            print '[duration.totalSeconds:N] seconds to read'
            print '[topDir.numBytes/_divisor:N] [_divisorLabel]'
            files = topDir.toList
            n = (files.count*_topPercent) to int
            for i in n
                f = files[i]
                size = f.numBytes / _divisor
                if size < _minSize, break  # small files are uninteresting
                #print '%4i %7.1f %s' % (i+1, size, f.pathname)
                istr = (i+1).toString.padLeft(4)
                sizestr = size.toString('0.0').padLeft(7)
                print '[istr] [sizestr] [f.pathName]'