Вот простое решение с использованием только собственных модулей fs
и path
:
// sync version
function walkSync(currentDirPath, callback) {
var fs = require('fs'),
path = require('path');
fs.readdirSync(currentDirPath).forEach(function (name) {
var filePath = path.join(currentDirPath, name);
var stat = fs.statSync(filePath);
if (stat.isFile()) {
callback(filePath, stat);
} else if (stat.isDirectory()) {
walkSync(filePath, callback);
}
});
}
или асинхронная версия (вместо нее используется fs.readdir
):
// async version with basic error handling
function walk(currentDirPath, callback) {
var fs = require('fs'),
path = require('path');
fs.readdir(currentDirPath, function (err, files) {
if (err) {
throw new Error(err);
}
files.forEach(function (name) {
var filePath = path.join(currentDirPath, name);
var stat = fs.statSync(filePath);
if (stat.isFile()) {
callback(filePath, stat);
} else if (stat.isDirectory()) {
walk(filePath, callback);
}
});
});
}
Тогда вы просто звоните (для синхронизации):
walkSync('path/to/root/dir', function(filePath, stat) {
// do something with "filePath"...
});
или асинхронная версия:
walk('path/to/root/dir', function(filePath, stat) {
// do something with "filePath"...
});
Разница заключается в том, как блокируются узлы при выполнении ввода-вывода. Учитывая, что приведенный выше API-интерфейс одинаков, вы можете просто использовать асинхронную версию для обеспечения максимальной производительности.
Однако есть одно преимущество использования синхронной версии. Некоторый код легче выполнить, как только завершится обход, как в следующем операторе после обхода. В асинхронной версии вам понадобится дополнительный способ узнать, когда вы закончите. Возможно, сначала создайте карту всех путей, а затем перечислите их. Для простых сценариев сборки / утилит (против высокопроизводительных веб-серверов) вы можете использовать синхронизирующую версию без каких-либо повреждений.