-
Notifications
You must be signed in to change notification settings - Fork 0
/
TreeSize.ts
111 lines (90 loc) · 3.68 KB
/
TreeSize.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/// <reference path="commander.d.ts"/>
// Compile with: tsc --module CommonJS TreeSize.ts
import fs = require('fs');
import path = require('path');
import findit = require('findit');
import program = require('commander');
program
.version('0.0.1')
.option('-p, --path <path>', 'The path to the directory')
.option('-d, --depth <n>', 'The level of subdirectories to show', parseInt)
.option('-s, --size <n>', 'Limit output to subdirectories over <n>MB', parseInt)
.option('-f, --fullpath', 'Report the full path to the directories')
.parse(process.argv);
var options = program.opts();
interface Dir {
fullPath: string;
size: number;
totalSize: number;
subdirs: {[index: string]: Dir};
}
// Get the folder to start from
var root = options.path || process.cwd();
var minSize = options.size || 0;
var finder = findit(root);
var graph: Dir = { size: 0, totalSize: 0, subdirs: {}, fullPath: root};
finder.on('directory',(fullpath: string, stat: fs.Stats, stop: Function) => {
// Stats for directories do not set size. Note this does get called for the root dir first.
// Ensure it is added, so that even dirs with no files are captured
getDirInTree(fullpath);
});
finder.on('file',(fullpath: string, stat: fs.Stats) => {
addFileSizeToDir(fullpath, stat.size);
});
finder.on('end',() => {
var colWidth = 15;
var padding = " ";
var indent = 4;
var currIndent = 1;
var header = (padding + "Total size").slice(-colWidth);
var underl = (padding + "----------").slice(-colWidth);
header += (padding + "Folder size").slice(-colWidth);
underl += (padding + "-----------").slice(-colWidth);
header += " Folder name";
underl += " -----------";
console.log(header);
console.log(underl);
// Depth first recursion to roll up the each dir size to totalSize
getDirTotal(graph);
function getDirTotal(dir: Dir): number {
var total = dir.size;
for (var subdir in dir.subdirs) {
total = total + getDirTotal(dir.subdirs[subdir]);
}
return dir.totalSize = total;
}
writeDir(graph, root);
function writeDir(dir: Dir, name: string) {
if(options.size && dir.totalSize < (options.size * 1000000)) return;
if(options.depth && currIndent > options.depth) return;
var totalText = (padding + dir.totalSize).slice(-colWidth);
var sizeText = (padding + dir.size).slice(-colWidth);
var dirText = padding.slice(-(currIndent * indent)) + (options.fullpath ? dir.fullPath : name);
console.log(totalText + sizeText + dirText);
currIndent++;
for (var subdir in dir.subdirs) {
writeDir(dir.subdirs[subdir], subdir);
}
currIndent--;
}
});
function getDirInTree(fullPath: string): Dir {
// For root, this will result in an empty string and no parts
var relativePath = path.relative(root, fullPath);
var parts: string[] = relativePath.split(path.sep);
// For each part, find or create the resulting entry
var result = graph;
parts.forEach(part => {
if (!part) return; // Split an empty string (the root path) results in ['']
if (!(part in result.subdirs)) {
result.subdirs[part] = { size: 0, totalSize: 0, subdirs: {}, fullPath: fullPath};
}
result = result.subdirs[part];
});
return result;
}
function addFileSizeToDir(fullPath: string, size: number) {
var dir = path.dirname(fullPath);
var entry = getDirInTree(dir);
entry.size += size;
}