递归地查找基目录数组中的子目录

时间:2015-01-19 14:52:56

标签: javascript recursion firefox-addon

出于测试目的,我试图记录3个基本目录中包含多少(子)目录,但结果没有意义。
linux控制台输出与插件输出,子目录数量不匹配,例如

console.log: recursive: 7
console.info: recursive: time taken =  38ms
console.log: recursive: 7
console.info: recursive: time taken =  41ms
console.log: recursive: 35
console.info: recursive: time taken =  330ms
Total time: 7.571605 seconds
Program terminated successfully.
rob@work:~/git/recursiveDirListingFF$ find /home/rob/Pictures/ -mindepth 1 -type d | wc -l
1
rob@work:~/git/recursiveDirListingFF$ find /home/rob/Music/ -mindepth 1 -type d | wc -l
2
rob@work:~/git/recursiveDirListingFF$ find /home/rob/Downloads/ -mindepth 1 -type d | wc -l
37

任何人都可以看一下可能出错的建议吗? 这是代码main.js ..

var myBaseDirs = [];

myBaseDirs.push('/home/rob/Pictures');
myBaseDirs.push('/home/rob/Music');
myBaseDirs.push('/home/rob/Downloads');

require("./FileIO").list(myBaseDirs);

FileIO.js ..

var {
        Cu
    } = require("chrome"),
    {
        OS
    } = Cu.import("resource://gre/modules/osfile.jsm", {});

function compare(a, b) {
    if (a.filename < b.filename)
        return -1;
    if (a.filename > b.filename)
        return 1;
    return 0;
}

exports.list = function (dirs) {

    var audio = [],
        dirsTemp = [],
        checkedSubdirI = dirs.length - 1,
        sTime = new Date().getTime(),
        eTime = 0;

    for (var w = 0; w < dirs.length; w++) {
        dirsTemp.push(dirs[w]);
    }

    for (var k = 0; k < dirsTemp.length; k++) {

        let iterator = new OS.File.DirectoryIterator(dirsTemp[k]);

        var promise = iterator.forEach(
            function onEntry(entry) {
                if (entry.isDir) {
                    dirsTemp.push(entry);
                }
            }
        );

        var onSuc = function onSuccess() {
            iterator.close();
            if (checkedSubdirI === dirsTemp.length - 1) {
                eTime = new Date().getTime();
                console.log(dirsTemp.length);
                console.info('time taken = ', eTime - sTime + 'ms');
                return dirsTemp;
            } else {
                checkedSubdirI++;
                iterator = new OS.File.DirectoryIterator(dirsTemp[checkedSubdirI].path);
                promise = iterator.forEach(
                    function onEntry(entry) {
                        if (entry.isDir) {
                            dirsTemp.push(entry);
                        }
                    }
                );
                return promise.then(
                    onSuc,
                    onRej
                );
            }
        }

        var onRej = function onFailure(reason) {
                iterator.close();
                eTime = new Date().getTime();
                console.info('FAILED reason = ', reason, 'time taken = ', eTime - sTime + 'ms');
                throw reason;
            }
            // Finally, close the iterator
        promise.then(
            onSuc,
            onRej
        );
    }
};

1 个答案:

答案 0 :(得分:1)

这被证明是有用的:

https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm/OS.File.DirectoryIterator_for_the_main_thread#Example.3A_Iterating_through_all_child_entries_of_directory

//start - helper function
    function enumChildEntries(pathToDir, delegate, max_depth, runDelegateOnRoot, depth) {
    // IMPORTANT: as dev calling this functiopn `depth` arg must ALWAYS be null/undefined (dont even set it to 0). this arg is meant for internal use for iteration
    // `delegate` is required
    // pathToDir is required, it is string
    // max_depth should be set to null/undefined/<0 if you want to enumerate till every last bit is enumerated. paths will be iterated to including max_depth.
    // if runDelegateOnRoot, then delegate runs on the root path with depth arg of -1
    // this function iterates all elements at depth i, then after all done then it iterates all at depth i + 1, and then so on
    // if arg of `runDelegateOnRoot` is true then minimum depth is -1 (and is of the root), otherwise min depth starts at 0, contents of root

    var deferred_enumChildEntries = new Deferred();
    var promise_enumChildEntries = deferred_enumChildEntries.promise;

    if (depth === undefined || depth === undefined) {
        // at root pathDir
        depth = 0;
        if (runDelegateOnRoot) {
            var entry = {
                isDir: true,
                name: OS.Path.basename(pathToDir),
                path: pathToDir
            };
            var rez_delegate = delegate(entry, -1);
            if (rez_delegate) {
                deferred_enumChildEntries.resolve(entry);
                return promise_enumChildEntries; // to break out of this func, as if i dont break here it will go on to iterate through this dir
            }
        }
    } else {
        depth++;
    }

    if ((max_depth === null || max_depth === undefined) || ( depth <= max_depth)) {
        var iterrator = new OS.File.DirectoryIterator(pathToDir);
        var subdirs = [];
        var promise_batch = iterrator.nextBatch();
        promise_batch.then(
            function(aVal) {
                for (var i = 0; i < aVal.length; i++) {
                    if (aVal[i].isDir) {
                        subdirs.push(aVal[i]);
                    }
                    var rez_delegate_on_root = delegate(aVal[i], depth);
                    if (rez_delegate_on_root) {
                        deferred_enumChildEntries.resolve(aVal[i]);
                        return promise_enumChildEntries; //to break out of this if loop i cant use break, because it will get into the subdir digging, so it will not see the `return promise_enumChildEntries` after this if block so i have to return promise_enumChildEntries here
                    }
                }
                // finished running delegate on all items at this depth and delegate never returned true

                if (subdirs.length > 0) {
                    var promiseArr_itrSubdirs = [];
                    for (var i = 0; i < subdirs.length; i++) {
                        promiseArr_itrSubdirs.push(enumChildEntries(subdirs[i].path, delegate, max_depth, null, depth)); //the runDelegateOnRoot arg doesnt matter here anymore as depth arg is specified
                    }
                    var promiseAll_itrSubdirs = Promise.all(promiseArr_itrSubdirs);
                    promiseAll_itrSubdirs.then(
                        function(aVal) {
                            deferred_enumChildEntries.resolve('done iterating all - including subdirs iteration is done - in pathToDir of: ' + pathToDir);
                        },
                        function(aReason) {
                            var rejObj = {
                                promiseName: 'promiseAll_itrSubdirs',
                                aReason: aReason,
                                aExtra: 'meaning finished iterating all entries INCLUDING subitering subdirs in dir of pathToDir',
                                pathToDir: pathToDir
                            };
                            deferred_enumChildEntries.reject(rejObj);
                        }
                    ).catch(
                        function(aCaught) {
                            throw aCaught; //throw here as its not final catch
                        }
                    );
                } else {
                    deferred_enumChildEntries.resolve('done iterating all - no subdirs - in pathToDir of: ' + pathToDir);
                }
            },
            function(aReason) {
                var rejObj = {
                    promiseName: 'promise_batch',
                    aReason: aReason
                };
                if (aReason.winLastError == 2) {
                    rejObj.probableReason = 'targetPath dir doesnt exist';
                }
                deferred_enumChildEntries.reject(rejObj);
            }
        ).catch(
            function(aCaught) {
                throw aCaught;
            }
        );
    } else {
        deferred_enumChildEntries.resolve('max depth exceeded, so will not do it, at pathToDir of: ' + pathToDir);
    }

    return promise_enumChildEntries;
}
// end - helper function

/************ start usage **************/
    var totalEntriesEnummed = 0; //meaning total number of entries ran delegate on, includes root dir
var allPaths = [];
function delegate_handleEntry(entry) {
  // return true to make enumeration stop
  totalEntriesEnummed++;
  allPaths.push(entry.path);
  console.info('entry:', entry);
}

var pathToTarget = OS.Constants.Path.desktopDir;
var promise_enumEntries = enumChildEntries(pathToTarget, delegate_handleEntry, null /* get all files */, false);
promise_enumEntries.then(
  function(aVal) {
    console.log('Fullfilled - promise_enumEntries - ', aVal, 'allPaths:', allPaths);
    console.info('totalEntriesEnummed:', totalEntriesEnummed)
  },
  function(aReason) {
    console.error('Rejected - promise_enumEntries - ', aReason);
  }
).catch(
  function(aCatch) {
    console.error('Caught - promise_enumEntries - ', aCatch);
  }  
);