如何遍历所有文件,并支持暂停和继续

我创build了一个NodeJS(电子)代码来读取特定目录和子目录中的所有文件。 我不想使用太多的高清资源,为什么我在文件夹之间使用5ms的延迟。

现在我的问题。 我想如果我的NODE进程停止? 我希望能够从停止时继续。 我该怎么做?

换句话说:如何在所有的文件和文件夹中行走时保持当前状态的索引,所以我可以继续从停止的遍历。

谢谢

我的代码:

var walkAll=function(options){ var x=0 walk(options.dir,function(){}) function walk(dir,callback) { var files=fs.readdirSync(dir); var stat; async.eachSeries(files,function(file,next){ file=dir +'/' + file if (dir.match(/Recycle/)) return next() if (dir.match(/.git/)) return next() if (dir.match(/node_modules/)) return next() fs.lstat(file,function(err,stat){ if(err) return next() if(stat.mode==41398) return next() if (stat.isDirectory()) { setTimeout(function(file){ walk(file,next) }.bind(null,file),5) } else{ x++ if(false || x % 1000===0) console.log((new Date().valueOf()-start)/1000,x,file) next() } }) },function(){ callback() }) } } walkAll({ dir:'c:/', delay:1000 }); 

保留要访问的子目录列表,并在每次迭代中更新列表。

下例中的walk函数取前一状态,并返回下一个子目录的下一个状态的文件。

您可以在停止进程之前保存状态,然后加载保存的状态以在重新启动时继续遍历。

 function walk(state, readdir) { let files = [], next = []; while (state.length > 0) { try { const current = state.shift() files = readdir(current).map(file => current + '/' + file) next = state.concat(files) break } catch(e) {} } return [next, files] } function main() { const {writeFileSync: writeFile, readdirSync: readdir} = require('fs') const save = './walk.json' let state try { state = require(save) } catch(e) {} if (!state || state.length < 1) state = ['.'] const [nextState, files] = walk(state, readdir) console.log(files) writeFile(save, JSON.stringify(nextState, null, 2)) } main() 

一个替代的想法,

 var miss = require('mississippi') var fs = require("fs") var through2 = require("through2") var path = require("path") function traverseDir(dirPath) { var stack = [path.resolve(dirPath)]; var filesStack = [] return miss.from.obj(function(size, next) { if (filesStack.length) { return next(null, filesStack.shift()) } var self = this; try { while(stack.length) { readADir(stack.pop()).forEach(function (f) { if (ft=="d") { stack.push(fp) } filesStack.push(f) }) if (filesStack.length) { return next(null, filesStack.shift()) } } return next(null, null) }catch(ex) { return next(ex) } }) } function readADir (dir) { return fs.readdirSync(dir) .map(function (f) {return path.join(dir, f)}) .filter(function (f) { return !f.match(/\.git/) }) .filter(function (f) { return !f.match(/Recycle/)}) .filter(function (f) { return !f.match(/node_modules/)}) .map(function (p) { try { var stat = fs.lstatSync(p); if(stat.mode==41398) return null var t = stat.isDirectory() ? "d":"f" return { t: t, p: p } }catch (ex) {} return null }) .filter(function (o) {return o!==null}) } function loadState(base){ base = path.resolve(base) var state = {base: base, last:null} if (fs.existsSync("state.json")) { state = JSON.parse(fs.readFileSync("state.json")) } else { saveState(state) } return state } function saveState(state){ fs.writeFileSync("state.json", JSON.stringify(state)) } var state = loadState("..") var sincePath = state.last; var filesStream = traverseDir(state.base) .on('end', function () { console.log("end") }) .pipe(through2.obj(function (chunk, enc, next) { if(!sincePath) this.push(chunk) if(chunk.p===sincePath) { sincePath=null } next() })) var tr = through2.obj(function (chunk, enc, next) { state.last = chunk.p saveState(state) console.log("data %v %j", chunk.t, chunk.p) this.push(chunk) setTimeout(next, 500) }).resume() require('keypress')(process.stdin); process.stdin.on('keypress', function (ch, key) { if(!key) return if (key.name == "c") { console.log("continue") filesStream.pipe(tr) } else if (key.name=="p") { console.log("pause") filesStream.unpipe(tr) } }); console.log("Press 'c' to start")