Подтвердить что ты не робот

Лучший способ получить папку и список файлов в Javascript

Я использую node -webkit, и пытаюсь, чтобы пользователь выбирал папку, и я верну структуру каталогов этой папки и рекурсивно получаю ее дочерние элементы.

У меня это работает достаточно просто с этим кодом (в контроллере Angular).

var fs = require('fs');

    $scope.explorer=[];
    $scope.openFile = function(){
            $scope.explorer = [tree_entry($scope.path)];    
            get_folder($scope.path, $scope.explorer[0].children);
    };

    function get_folder(path, tree){
        fs.readdir(path, function(err,files){
            if (err) return console.log(err);

            files.forEach( function (file,idx){
                tree.push(tree_entry(file));
                fs.lstat(path+'/'+file,function(err,stats){
                    if(err) return console.log(err);
                    if(stats.isDirectory()){
                        get_folder(path+'/'+file,tree[idx].children);
                    }
                });
            });
        });
        console.log($scope.explorer);

        return;
    }

    function tree_entry(entry){
        return { label : entry, children: []}
    }

Взяв папку умеренного размера с 22 дочерними папками и примерно на 4 уровня глубиной, потребуется всего несколько минут, чтобы получить всю структуру каталогов.

Есть ли что-то, что я, очевидно, здесь делаю неправильно? Я не могу поверить, что это так долго, потому что я использую встроенные методы Node fs. Или есть способ получить все содержимое каталога, не касаясь каждого файла?

Я хочу, чтобы иметь возможность использовать фильтр Angular в именах файлов, вплоть до дерева, и, возможно, от содержимого, поэтому отсрочка обработки всего дерева вряд ли будет решением, которое должно сработать.

4b9b3361

Ответ 1

В моем проекте я использую эту функцию для получения огромного количества файлов. Это довольно быстро (поместите require("FS"), чтобы сделать это еще быстрее):

var _getAllFilesFromFolder = function(dir) {

    var filesystem = require("fs");
    var results = [];

    filesystem.readdirSync(dir).forEach(function(file) {

        file = dir+'/'+file;
        var stat = filesystem.statSync(file);

        if (stat && stat.isDirectory()) {
            results = results.concat(_getAllFilesFromFolder(file))
        } else results.push(file);

    });

    return results;

};

ясно:

_getAllFilesFromFolder(__dirname + "folder");

Ответ 2

Зачем изобретать колесо?

Существует очень популярный пакет NPM, который позволяет вам делать такие вещи легко.

var recursive = require("recursive-readdir");

recursive("some/path", function (err, files) {
  // 'files' is an array of file paths
  console.log(files);
});

Узнайте больше:

Ответ 3

Мне не нравится добавлять новый пакет в мой проект просто для решения этой простой задачи.

Кроме того, я стараюсь изо всех сил избегать рекурсивного алгоритма.... поскольку в большинстве случаев он медленнее, чем нерекурсивный.

Поэтому я сделал функцию для получения всего содержимого папки (и ее подпапки).... НЕ-рекурсивно

var getDirectoryContent = function(dirPath) {
    /* 
        get list of files and directories from given dirPath and all it sub directories
        NON RECURSIVE ALGORITHM
        By. Dreamsavior
    */
    var RESULT = {'files':[], 'dirs':[]};

    var fs = fs||require('fs');
    if (Boolean(dirPath) == false) {
        return RESULT;
    }
    if (fs.existsSync(dirPath) == false) {
        console.warn("Path does not exist : ", dirPath);
        return RESULT;
    }

    var directoryList = []
    var DIRECTORY_SEPARATOR = "\\";
    if (dirPath[dirPath.length -1] !== DIRECTORY_SEPARATOR) dirPath = dirPath+DIRECTORY_SEPARATOR;

    directoryList.push(dirPath); // initial

    while (directoryList.length > 0) {
        var thisDir  = directoryList.shift(); 
        if (Boolean(fs.existsSync(thisDir) && fs.lstatSync(thisDir).isDirectory()) == false) continue;

        var thisDirContent = fs.readdirSync(thisDir);
        while (thisDirContent.length > 0) { 
            var thisFile  = thisDirContent.shift(); 
            var objPath = thisDir+thisFile

            if (fs.existsSync(objPath) == false) continue;
            if (fs.lstatSync(objPath).isDirectory()) { // is a directory
                let thisDirPath = objPath+DIRECTORY_SEPARATOR; 
                directoryList.push(thisDirPath);
                RESULT['dirs'].push(thisDirPath);

            } else  { // is a file
                RESULT['files'].push(objPath); 

            } 
        } 

    }
    return RESULT;
}

единственный недостаток этой функции в том, что это синхронная функция... Вы были предупреждены;)