Skip to content

Instantly share code, notes, and snippets.

@creationix
Created February 10, 2010 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save creationix/300639 to your computer and use it in GitHub Desktop.
Save creationix/300639 to your computer and use it in GitHub Desktop.
Scan a directory for files and read them all into an object indexed by filename. Async and Sync versions of code.
var File = require('file'),
Sys = require('sys'),
Posix = require('posix');
// Sync api wrapper around some Posix commands
// Sells it soul to `wait`.
var posix_sync = {
readdir: function (path) {
return Posix.readdir(path).wait();
},
stat: function (filename) {
return Posix.stat(filename).wait();
},
cat: function (filename) {
return Posix.cat(filename).wait();
}
}
// Async api wrapper around some Posix commands
// Uses continuable style for cleaner syntax
var posix = {
readdir: function (path) { return function (next) {
Posix.readdir(path).addCallback(next);
}},
stat: function (filename) { return function (next) {
Posix.stat(filename).addCallback(next);
}},
cat: function (filename) { return function (next) {
Posix.cat(filename).addCallback(next);
}}
}
// Scan a directory for files
// Filter out directories
// Read contents of files
// Here is the sync version:
function scandir_sync(path) {
return posix_sync.readdir(path).filter(function (filename) {
return posix_sync.stat(filename).isFile();
}).map(function (filename) {
return [filename, posix_sync.cat(filename)];
});
}
// debug(scandir_sync(__dirname));
// Here is the async version without helpers
function scandir1(path) { return function (next) {
posix.readdir(path)(function (filenames) {
var realfiles = [];
var count = filenames.length;
filenames.forEach(function (filename) {
posix.stat(filename)(function (stat) {
if (stat.isFile()) {
realfiles.push(filename);
}
count--;
if (count <=0) {
var results = [];
realfiles.forEach(function (filename) {
posix.cat(filename)(function (data) {
results.push([filename, data]);
if (results.length === realfiles.length) {
next(results);
}
});
});
}
});
});
});
}}
// Here is the async version with filter and map helpers:
function scandir2(path) { return function (next) {
posix.readdir(path)(function (filenames) {
filter(filenames, function (filename, callback) {
posix.stat(filename)(function (stat) {
callback(stat.isFile());
});
})(function (filenames) {
map(filenames, function (filename, callback) {
posix.cat(filename)(function (data) {
callback([filename, data]);
});
})(next);
});
});
}}
// Here is the async version with a combined filter and map helper:
function scandir3(path) { return function (next) {
posix.readdir(path)(function (filenames) {
filter_map(filenames, function (filename, callback) {
posix.stat(filename)(function (stat) {
if (stat.isFile()) {
posix.cat(filename)(function (data) {
callback([filename, data]);
});
} else {
callback();
}
});
})(next);
});
}}
scandir3(__dirname)(debug);
//////////////////////////////////////////////////////////////////////////////
// Utilities //
//////////////////////////////////////////////////////////////////////////////
// Quick wrapper around puts and inspect
function debug() {
Sys.puts(Sys.inspect.apply(this, arguments));
}
function map(array, callback) { return function (next) {
var counter = array.length;
var new_array = [];
array.forEach(function (item, index) {
callback(item, function (result) {
new_array[index] = result;
counter--;
if (counter <= 0) {
new_array.length = array.length
next(new_array);
}
});
});
}}
function filter(array, callback) { return function (next) {
var counter = array.length;
var valid = {};
array.forEach(function (item, index) {
callback(item, function (result) {
valid[index] = result;
counter--;
if (counter <= 0) {
var result = [];
array.forEach(function (item, index) {
if (valid[index]) {
result.push(item);
}
});
next(result);
}
});
});
}}
function filter_map(array, callback) { return function (next) {
var counter = array.length;
var new_array = [];
array.forEach(function (item, index) {
callback(item, function (result) {
new_array[index] = result;
counter--;
if (counter <= 0) {
new_array.length = array.length;
next(new_array.filter(function (item) {
return typeof item !== 'undefined';
}));
}
});
});
}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment