Implemented asynchronous recursive readdir #18
6 changed files with 140 additions and 36 deletions
|
|
@ -55,6 +55,70 @@ exports.readdirSyncRecursive = function(baseDir) {
|
||||||
return fileList;
|
return fileList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* wrench.readdirRecursive("directory_path", function(error, files) {});
|
||||||
|
*
|
||||||
|
* Recursively dives through directories and read the contents of all the
|
||||||
|
* children directories.
|
||||||
|
*
|
||||||
|
* Asynchronous, so returns results/error in callback.
|
||||||
|
* Callback receives the of files in currently recursed directory.
|
||||||
|
* When no more directories are left, callback is called with null for all arguments.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
exports.readdirRecursive = function(baseDir, fn) {
|
||||||
|
baseDir = baseDir.replace(/\/$/, '');
|
||||||
|
|
||||||
|
var waitCount = 0;
|
||||||
|
|
||||||
|
function readdirRecursive(curDir) {
|
||||||
|
var files = [],
|
||||||
|
curFiles,
|
||||||
|
nextDirs,
|
||||||
|
prependcurDir = function(fname){
|
||||||
|
return _path.join(curDir, fname);
|
||||||
|
};
|
||||||
|
|
||||||
|
waitCount++;
|
||||||
|
fs.readdir(curDir, function(e, curFiles) {
|
||||||
|
waitCount--;
|
||||||
|
|
||||||
|
curFiles = curFiles.map(prependcurDir);
|
||||||
|
|
||||||
|
curFiles.forEach(function(it) {
|
||||||
|
waitCount++;
|
||||||
|
|
||||||
|
fs.stat(it, function(e, stat) {
|
||||||
|
waitCount--;
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
fn(e);
|
||||||
|
} else {
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
readdirRecursive(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitCount == 0) {
|
||||||
|
fn(null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
fn(null, curFiles.map(function(val) {
|
||||||
|
// convert absolute paths to relative
|
||||||
|
return val.replace(baseDir + '/', '');
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (waitCount == 0) {
|
||||||
|
fn(null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
readdirRecursive(baseDir);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
|
/* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
|
||||||
*
|
*
|
||||||
|
|
|
||||||
18
readme.md
18
readme.md
|
|
@ -18,7 +18,10 @@ Usage
|
||||||
``` javascript
|
``` javascript
|
||||||
var wrench = require('wrench'),
|
var wrench = require('wrench'),
|
||||||
util = require('util');
|
util = require('util');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Synchronous operations
|
||||||
|
``` javascript
|
||||||
// Recursively create directories, sub-trees and all.
|
// Recursively create directories, sub-trees and all.
|
||||||
wrench.mkdirSyncRecursive(dir, 0777);
|
wrench.mkdirSyncRecursive(dir, 0777);
|
||||||
|
|
||||||
|
|
@ -43,6 +46,19 @@ while(f.hasNextLine()) {
|
||||||
util.puts(x.getNextLine());
|
util.puts(x.getNextLine());
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
It should be noted that these are all currently synchronous operations.
|
|
||||||
|
### Asynchronous operations
|
||||||
|
``` javascript
|
||||||
|
// Recursively read directories contents
|
||||||
|
var files = [];
|
||||||
|
wrench.readdirRecursive('my_directory_name', function(error, curFiles) {
|
||||||
|
if (files) {
|
||||||
|
files = files.concat(curFiles);
|
||||||
|
} else {
|
||||||
|
// files list contains all the directory contents now
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
Questions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)
|
Questions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)
|
||||||
|
|
|
||||||
57
tests/readdir.js
Normal file
57
tests/readdir.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
var testCase = require('nodeunit').testCase;
|
||||||
|
var fs = require('fs');
|
||||||
|
var wrench = require('../lib/wrench');
|
||||||
|
var path = require('path');
|
||||||
|
var _und = require("underscore");
|
||||||
|
|
||||||
|
|
||||||
|
function checkResult(test, files) {
|
||||||
|
var check = [
|
||||||
|
'bar.txt',
|
||||||
|
'foo',
|
||||||
|
'foo/bar',
|
||||||
|
'foo/dolor.md',
|
||||||
|
'foo/lorem.txt',
|
||||||
|
'foo/bar/ipsum.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
test.equals(files.length, check.length, 'number of paths is correct');
|
||||||
|
|
||||||
|
_und.each(check, function(it) {
|
||||||
|
test.ok(_und.include(files, it), 'path ' + it + ' should be returned');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = testCase({
|
||||||
|
test_readdirSyncRecursive: function(test) {
|
||||||
|
var dir = __dirname + '/readdir';
|
||||||
|
|
||||||
|
test.ok(path.existsSync(dir), 'Folders should exist');
|
||||||
|
|
||||||
|
var files = wrench.readdirSyncRecursive(dir);
|
||||||
|
|
||||||
|
checkResult(test, files);
|
||||||
|
},
|
||||||
|
|
||||||
|
test_readdirRecursive: function(test) {
|
||||||
|
var dir = __dirname + '/readdir';
|
||||||
|
|
||||||
|
test.ok(path.existsSync(dir), 'Folders should exist');
|
||||||
|
|
||||||
|
var allFiles = [];
|
||||||
|
|
||||||
|
wrench.readdirRecursive(dir, function(e, files) {
|
||||||
|
if (e) throw e;
|
||||||
|
|
||||||
|
if (files) {
|
||||||
|
allFiles = allFiles.concat(files);
|
||||||
|
} else {
|
||||||
|
checkResult(test, allFiles);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// vim: et ts=4 sw=4
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
var testCase = require('nodeunit').testCase;
|
|
||||||
var fs = require('fs');
|
|
||||||
var wrench = require('../lib/wrench');
|
|
||||||
var path = require('path');
|
|
||||||
var _und = require("underscore");
|
|
||||||
|
|
||||||
module.exports = testCase({
|
|
||||||
test_readdirSyncRecursive: function(test) {
|
|
||||||
var dir = __dirname + '/readdir';
|
|
||||||
|
|
||||||
test.equals(path.existsSync(dir), true, 'Folders should exist');
|
|
||||||
|
|
||||||
var check = [
|
|
||||||
'bar.txt',
|
|
||||||
'foo',
|
|
||||||
'foo/bar',
|
|
||||||
'foo/dolor.md',
|
|
||||||
'foo/lorem.txt',
|
|
||||||
'foo/bar/ipsum.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
var files = wrench.readdirSyncRecursive(dir);
|
|
||||||
|
|
||||||
test.equals(files.length, check.length, 'number of paths is correct');
|
|
||||||
for (var filename in files) {
|
|
||||||
test.ok(_und.include(check, files[filename]));
|
|
||||||
}
|
|
||||||
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// vim: et ts=4 sw=4
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
// will run all the tests
|
// will run all the tests
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
group_mkdirSyncRecursive : require('./mkdirSyncRecursive'),
|
group_mkdir: require('./mkdir'),
|
||||||
group_readdirSyncRecursive : require('./readdirSyncRecursive')
|
group_readdir: require('./readdir')
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Reference in a new issue