Created
September 6, 2011 23:37
-
-
Save goatslacker/1199305 to your computer and use it in GitHub Desktop.
returns amount of space available on a system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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