first commit

This commit is contained in:
AJ ONeal 2010-11-20 22:02:53 -07:00
commit 8462d7458b
5 changed files with 340 additions and 0 deletions

165
README.md Normal file
View File

@ -0,0 +1,165 @@
node-walk
====
A not-quite-port of python's `os.walk`.
Installation
----
npm install walk
Usage
====
var walk = require('walk'),
options = {
followlinks: false,
topdown: false, // currently ignored
};
function fileHandler(err, path, nodes, sorted) {
// handle each path
}
walk("path/to/dir", options, fileHandler);
// This also works
// walk("path/to/dir", options).whenever(fileHandler);
* err - Probably can't read a directory due to permissions.
* path - the current path being read
* nodes - an array of `stats`
* sorted - `nodes` sorted by type
* `errors` - nodes that could not be `stat`ed and why
* `files` - actual files (or links)
* `dirs`
* `blocks`
* `chars`
* `links`
* `fifos`
* `sockets`
Example
====
mkdir -p walk-test/dir1
touch walk-test/file-1
touch walk-test/file-2
touch walk-test/dir1/file-1
touch walk-test/dir1/file-2
node-walk-test
----
var walk = require('walk');
walk('./walk-test', undefined, function (err, path, nodes, sorted) {
if (err) {
console.log('ERROR: ');
console.log(err);
return;
}
o.dirs.forEach(function (item, i, arr) {
if (item.name.match(/trash/i)) {
console.log('found a trash');
arr.splice(i,1);
}
});
console.log("PATH: " + path);
console.log("SORTED: ");
console.log(o);
});
Output
----
PATH: ./walk-test
SORTED:
{ errors: [],
files:
[ { dev: 234881026,
ino: 30682245,
mode: 33204,
nlink: 1,
uid: 504,
gid: 20,
rdev: 0,
size: 0,
blksize: 4096,
blocks: 0,
atime: Sun, 21 Nov 2010 04:48:23 GMT,
mtime: Sun, 21 Nov 2010 04:48:23 GMT,
ctime: Sun, 21 Nov 2010 04:48:23 GMT,
name: 'file-1' },
{ dev: 234881026,
ino: 30682246,
mode: 33204,
nlink: 1,
uid: 504,
gid: 20,
rdev: 0,
size: 0,
blksize: 4096,
blocks: 0,
atime: Sun, 21 Nov 2010 04:48:23 GMT,
mtime: Sun, 21 Nov 2010 04:48:23 GMT,
ctime: Sun, 21 Nov 2010 04:48:23 GMT,
name: 'file-2' } ],
dirs:
[ { dev: 234881026,
ino: 30682244,
mode: 16893,
nlink: 4,
uid: 504,
gid: 20,
rdev: 0,
size: 136,
blksize: 4096,
blocks: 0,
atime: Sun, 21 Nov 2010 04:49:40 GMT,
mtime: Sun, 21 Nov 2010 04:48:23 GMT,
ctime: Sun, 21 Nov 2010 04:48:23 GMT,
name: 'dir1' } ],
blocks: [],
chars: [],
links: [],
fifos: [],
sockets: [] }
PATH: walk-test/dir1
SORTED:
{ errors: [],
files:
[ { dev: 234881026,
ino: 30682247,
mode: 33204,
nlink: 1,
uid: 504,
gid: 20,
rdev: 0,
size: 0,
blksize: 4096,
blocks: 0,
atime: Sun, 21 Nov 2010 04:48:23 GMT,
mtime: Sun, 21 Nov 2010 04:48:23 GMT,
ctime: Sun, 21 Nov 2010 04:48:23 GMT,
name: 'file-1' },
{ dev: 234881026,
ino: 30682248,
mode: 33204,
nlink: 1,
uid: 504,
gid: 20,
rdev: 0,
size: 0,
blksize: 4096,
blocks: 0,
atime: Sun, 21 Nov 2010 04:48:23 GMT,
mtime: Sun, 21 Nov 2010 04:48:23 GMT,
ctime: Sun, 21 Nov 2010 04:48:23 GMT,
name: 'file-2' } ],
dirs: [],
blocks: [],
chars: [],
links: [],
fifos: [],
sockets: [] }

128
lib/walk.js Normal file
View File

@ -0,0 +1,128 @@
(function () {
var fs = require('fs'),
Futures = require('futures'),
joinPath = require('path').join,
util = require('util'),
dir = process.argv[2];
function sortNodesByType(stats, o) {
if (stats.isFile()) {
o.files.push(stats);
} else if (stats.isDirectory()) {
o.dirs.push(stats);
} else if (stats.isBlockDevice()) {
o.blocks.push(stats);
} else if (stats.isCharacterDevice()) {
o.chars.push(stats);
} else if (stats.isSymbolicLink()) {
o.links.push(stats);
} else if (stats.isFIFO()) {
o.fifos.push(stats);
} else if (stats.isSocket()) {
o.sockets.push(stats);
} else {
util.debug(stats.node + 'is not of any node type');
}
}
/*
import os
from os.path import join, getsize
for root, dirs, files in os.walk('python/Lib/email'):
print root, "consumes",
print sum(getsize(join(root, name)) for name in files),
print "bytes in", len(files), "non-directory files"
if 'CVS' in dirs:
dirs.remove('CVS') # don't visit CVS directories
*/
/*
fs.walk(path, function ({ err, root, dirs, files }) {}, {
// currently ignored
topdown: boolean,
onerror: boolean, // ignored
followlinks: boolean // lstat or stat
});
*/
function walk(firstPath, options, callback) {
options = options || {};
var fstat = options.followlinks ? fs.stat : fs.lstat,
subscription = Futures.subscription();
if (callback) { subscription.subscribe(callback); }
function readDir(path) {
var p = Futures.promise();
fs.readdir(path, function (err, files) {
if (err) {
err.path = path;
subscription.deliver(err, path, undefined, undefined);
// Signal the completion of this readdir attempt
p.fulfill();
return;
}
// TODO fix futures sequence to not require a first function like this
var s = Futures.sequence(function(n){n();}),
nodes = [],
o = {
errors: [],
files: [],
dirs: [],
blocks: [],
chars: [],
links: [],
fifos: [],
sockets: []
};
files.forEach(function (file) {
s.then(function (next) {
fstat(joinPath(path, file), function (err, stats) {
stats = stats || {};
stats.name = file;
nodes.push(stats);
if (err) {
stats.err = err;
o.errors.push(stats);
} else {
sortNodesByType(stats, o);
}
next();
});
});
});
s.then(function (next) {
var s2 = Futures.sequence(function(n){n();});
subscription.deliver(undefined, path, nodes, o);
p.fulfill();
o.dirs.forEach(function (dir) {
s2.then(function (next2) {
readDir(joinPath(path, dir.name))
.when(function () { next2(); });
});
});
next();
});
});
return p.passable();
}
readDir(firstPath) //.whenever(callback);
return {
whenever: subscription.subscribe
}
}
module.exports = walk;
}());

12
package.json Normal file
View File

@ -0,0 +1,12 @@
{
"name" : "walk",
"description" : "A node port of python's os.walk",
"url" : "github.com/coolaj86/walk",
"keywords" : ["util", "os", "fs", "walk"],
"author" : "AJ ONeal <coolaj86@gmail.com>",
"contributors" : [],
"dependencies" : ["futures"],
"lib" : "lib",
"main" : "./lib/walk.js",
"version" : "0.9.1"
}

30
walk-test.js Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env node
(function () {
var walk = require('./lib/walk');
Array.prototype.removeAt = function (i) {
return this.splice(i, 1)[0];
}
walk('./walk-test').whenever(function (err, path, nodes, o) {
if (err) {
console.log('ERROR: ');
console.log(err);
return;
}
o.dirs.forEach(function (item, i, arr) {
if (item.name.match(/trash/i)) {
console.log('found a trash');
arr.removeAt(i);
}
});
console.log("PATH: " + path);
console.log("SORTED: ");
console.log(o);
});
setTimeout(function () {
process.nextTick(process.exit);
}, 200);
}());

5
walk-test.sh Executable file
View File

@ -0,0 +1,5 @@
mkdir -p walk-test/dir1
touch walk-test/file-1
touch walk-test/file-2
touch walk-test/dir1/file-1
touch walk-test/dir1/file-2