Wiki

root/cobra/trunk/Samples/Sizes.cobra

Revision 1982, 5.4 KB (checked in by Chuck.Esterbrook, 3 years ago)

Updated Samples to represent the latest Cobra syntax.

  • Property svn:eol-style set to native
Line 
1"""
2sizes.cobra
3
4The most effective technique to free up disk space on a drive is to look in the
5directories that consume the most space. You may find entire directories that
6can be deleted or excessively large files that are no longer needed. The first
7time you do this, you might downsize the space consumed by a large factor with
8only a few minutes of effort. Credit goes to the old "Dark Forest" application
9on the old NeXTstep platform for introducing me to this approach.
10
11This command line utility scans the current directory and its files for their
12sizes, including all subdirectories. It then reports the total size and shows
13the largest directories and files first. You can use this report to look for
14large things to delete and rerun it as you progress. To run:
15
16> cd \to\path\of\interest
17> cobra \path\to\sizes.cobra
18
19Unix users get a similar result with something like "du -k | sort -nr"
20
21As an example, I ran `sizes` on a directory and it reported:
22
23203658 directories and files read
24180.30 seconds to read
2521,297.34 MB
26
27After spending 20 minutes cleaning up the biggest directories and files
28that it listed, it then reported this:
29
30186345 directories and files read
3149.95 seconds to read
328,809.15 MB
33"""
34
35class FileNode implements IComparable
36    """
37    One of these will be created for every directory and file, and put into a
38    list that can be sorted.
39    """
40
41    test
42        a = FileNode('a', 100)
43        assert a.pathName == 'a'
44        assert a.numBytes == 100
45        assert a.compareTo(nil) == 1
46        b = FileNode('b', 200)
47        assert a.compareTo(b) < 0
48        assert b.compareTo(a) > 0
49        c = FileNode('c', 100)
50        assert a.compareTo(c) == 0
51
52    var _pathName as String
53    var _numBytes as decimal
54
55    cue init(pathName as String, numBytes as decimal)
56        _pathName = pathName
57        _numBytes = numBytes
58
59    get pathName from _pathName
60
61    get numBytes from _numBytes
62
63    def compareTo(obj as Object?) as int
64        require
65            obj is nil  or  obj inherits FileNode
66        body
67            if obj is nil
68                return 1
69            else if obj inherits FileNode
70                return _numBytes.compareTo(obj.numBytes)
71            else
72                throw FallThroughException(obj)
73
74
75class Dir
76    """
77    Dir does the work of scanning the files and subdirectories.
78    This results in a tree-like structure that matches the file system.
79    """
80
81    shared
82        var _sep    as char   # Path.directorySeparatorChar
83
84    var _di         as DirectoryInfo
85    var _dir        as Dir?  # parent directory
86    var _baseName   as String
87    var _pathName   as String
88
89    var _files      as List<of FileInfo>
90    var _subdirs    as List<of Dir>
91
92    var _count      as int
93    var _numBytes   as decimal  # using 'decimal' because FileInfo.length returns int64
94
95    cue init(pathName as String)
96        """ Creates a Dir from a filesystem path string. Scans all subdirs. """
97        _di = DirectoryInfo(pathName)
98        _pathName = pathName
99        _baseName = pathName
100        _init(nil)
101
102    cue init(di as DirectoryInfo, parentDir as Dir)
103        """ Creates a Dir from a parent Dir. Scans all subdirs. """
104        _di = di
105        _baseName = di.name
106        _pathName = di.fullName
107        _init(parentDir)
108
109    get count from _count
110
111    get numBytes from _numBytes
112
113    def _init(parentDir as Dir?)
114        assert _baseName.length
115        _sep = Path.directorySeparatorChar
116        _dir = parentDir
117        if _dir, _pathName = '[_dir._pathName][_sep][_baseName]'
118        _files = List<of FileInfo>()
119        _subdirs = List<of Dir>()
120        .scan
121
122    def scan
123        assert _pathName.length
124
125        try
126            dirInfo = DirectoryInfo(_pathName)
127        catch IOException
128            print 'warning: Unreadable directory:', _pathName
129            return
130
131        try
132            files = dirInfo.getFiles
133        catch IOException
134            print 'warning: Unreadable files in directory:', _pathName
135            return
136
137        for fi in files
138            try
139                _files.add(fi)
140                _count += 1
141                _numBytes += fi.length to decimal
142            catch IOException
143                print 'warning: Cannot scan file:', fi.fullName
144
145        for di in dirInfo.getDirectories
146            d = Dir(di, this)
147            _subdirs.add(d)
148            _count += d.count
149            _numBytes += d.numBytes
150       
151    get toList as List<of FileNode>
152        """
153        Returns a flat list containing self, all files and all subdirs (recursively).
154        """
155        t = List<of FileNode>()
156        .populateList(t)
157        return t
158
159    def populateList(t as List<of FileNode>) is protected
160        ensure
161            t.count > old t.count
162        body
163            t.add(FileNode(_pathName, _numBytes))
164            for fi in _files
165                try
166                    t.add(FileNode(fi.fullName, fi.length))
167                catch IOException
168                    print 'warning: Cannot scan file:', fi.fullName
169            for subdir in _subdirs
170                subdir.populateList(t)
171
172
173class Sizes
174
175    test
176        assert _topPercent > 0.0 and _topPercent <= 1.0
177        assert _divisor > 0.0
178        assert _minSize >= 0.0
179
180    shared
181        var _topPercent = 0.1
182        var _divisor = 1024 * 1024.0  # megabyte
183        var _minSize = 1.0  # expressed in terms of _divisor
184        var _divisorLabel = 'MB'
185
186        def main
187            print 'Scanning...'
188            Console.out.flush
189            start = DateTime.now
190            args = CobraCore.commandLineArgs
191            dirName = if(args.count > 1, args[1], Directory.getCurrentDirectory)
192            topDir = Dir(dirName)
193            duration = DateTime.now.subtract(start)
194            print
195            print '[topDir.count] directories and files read'
196            print '[duration.totalSeconds:N] seconds to read'
197            print '[topDir.numBytes/_divisor:N] [_divisorLabel]'
198            print
199            files = topDir.toList
200            files.sort
201            files.reverse
202            n = (files.count*_topPercent) to int
203            for i in n
204                f = files[i]
205                size = f.numBytes / _divisor
206                if size < _minSize, break  # small files are uninteresting
207                #print '%4i %7.1f %s' % (i+1, size, f.pathname)
208                istr = (i+1).toString.padLeft(4)
209                sizestr = size.toString('0.0').padLeft(7)
210                print '[istr] [sizestr] [f.pathName]'
Note: See TracBrowser for help on using the browser.