Лучший способ получить папку и список файлов в 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 в именах файлов, вплоть до дерева, и, возможно, от содержимого, поэтому отсрочка обработки всего дерева вряд ли будет решением, которое должно сработать.
Ответы
Ответ 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;
}
единственный недостаток этой функции в том, что это синхронная функция... Вы были предупреждены;)