Skip to content

Instantly share code, notes, and snippets.

@goatslacker
Created September 6, 2011 23:37
Show Gist options
  • Save goatslacker/1199305 to your computer and use it in GitHub Desktop.
Save goatslacker/1199305 to your computer and use it in GitHub Desktop.
returns amount of space available on a system
const fs = require('fs');
const path = require('path');
// FIXME - performance issue: When checking a directory which contains MANY nested directories
// the performance of this script suffers...
// most commonly found with svn projects that are > 500mb.
// perhaps we're stacking the stack way too high and need to pile through it before we can continue
// to add to it?
/**
Asynchronous function that retrieves the amount of space a particular directory takes up
@param {string} dir is the directory for which to scan
@param {Function} cb is the callback that fires once we have a size and @return {integer} size
*/
var getSpace = function (dir, cb) {
// the total space
var size = 0;
// stack we use to determine when we fire the callback
var stack = {};
// define the properties as non-enumerable so we don't break stuff
Object.defineProperties(stack, {
getLength: {
value: function () {
return Object.keys(this).length;
},
enumerable: false
},
remove: {
value: function (dirname, file) {
// dirname is mandatory
if (!dirname) {
return;
}
// if a file was passed, we attempt to remove it from the stack
if (file) {
var index = this[dirname].indexOf(file);
if (index >= 0) {
this[dirname].splice(index, 1);
}
}
// we remove an item from the stack once it's array is empty
if (!this[dirname] || this[dirname].length === 0) {
delete this[dirname];
}
// if there are no items in the stack, we can safely call the callback with the size
if (this.getLength() === 0) {
cb(null, size);
}
},
enumerable: false
}
});
// adds file size to our total size
var addSize = function (fileSize) {
size += fileSize;
};
// performs appropriate action for filetype dir | file
var getTypeOf = function (dirname, file) {
var fullpath = path.join(dirname, file);
// stat the file
fs.stat(fullpath, function (err, stats) {
// error returns error to callback
if (err) {
return cb(err);
}
// if it's a directory, dive in and remove the file
// TODO delay the directory check until files have been sized...
// I'm hoping this will fix performance issues
if (stats.isDirectory()) {
readDirectory(fullpath);
stack.remove(dirname, file);
// if it's a file then we calculate the size
} else if (stats.isFile()) {
addSize(stats.size);
stack.remove(dirname, file);
}
});
};
// reads a set of files inside a directory
var readFiles = function (dirname) {
return function (err, files) {
// if there are files, we add the files to the stack
// and then we loop through each file and read it's type
if (files && files.length > 0) {
stack[dirname] = files;
files.forEach(function (file, index) {
getTypeOf(dirname, file);
});
// otherwise we remove the stack
} else {
stack.remove(dirname, null);
}
};
};
// reads a directory -- main entry point of the getSpace function
var readDirectory = function (dirname) {
stack[dirname] = null;
fs.readdir(dirname, readFiles(dirname));
};
readDirectory(dir);
};
// converts bytes to a human readable format
var convertBytes = function (rawSize) {
const KB = 1024;
const MB = Math.pow(1024, 2);
const GB = Math.pow(1024, 3);
const TB = Math.pow(1024, 4);
var size = 0;
var identifier = "bytes";
if (rawSize > TB) {
identifier = "TB";
size = (rawSize / TB);
}
else if (rawSize > GB) {
identifier = "GB";
size = (rawSize / GB);
}
else if (rawSize > MB) {
identifier = "MB";
size = (rawSize / MB);
}
else if (rawSize > KB) {
identifier = "KB";
size = (rawSize / KB);
} else {
size = rawSize;
}
return (Math.round(size * 100) / 100) + identifier;
};
// CLI
if (process.argv.length > 1) {
getSpace(process.argv[2], function (err, size) {
// callback get's called more than once if errors are found...
// so just output to console if errors are found.
if (err) {
console.error(err.message);
}
// if we have a size, then let's convert it and display it
if (typeof size !== "undefined") {
console.log(convertBytes(size));
}
});
}
// NODE
module.exports = getSpace;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment