Last active
December 5, 2024 14:01
-
-
Save lovasoa/8691344 to your computer and use it in GitHub Desktop.
Walk through a directory recursively in node.js.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ES6 version using asynchronous iterators, compatible with node v10.0+ | |
const fs = require("fs"); | |
const path = require("path"); | |
async function* walk(dir) { | |
for await (const d of await fs.promises.opendir(dir)) { | |
const entry = path.join(dir, d.name); | |
if (d.isDirectory()) yield* walk(entry); | |
else if (d.isFile()) yield entry; | |
} | |
} | |
// Then, use it with a simple async for loop | |
async function main() { | |
for await (const p of walk('/tmp/')) | |
console.log(p) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Callback-based version for old versions of Node | |
var fs = require("fs"), | |
path = require("path"); | |
function walk(dir, callback) { | |
fs.readdir(dir, function(err, files) { | |
if (err) throw err; | |
files.forEach(function(file) { | |
var filepath = path.join(dir, file); | |
fs.stat(filepath, function(err,stats) { | |
if (stats.isDirectory()) { | |
walk(filepath, callback); | |
} else if (stats.isFile()) { | |
callback(filepath, stats); | |
} | |
}); | |
}); | |
}); | |
} | |
if (exports) { | |
exports.walk = walk; | |
} else { | |
walk(".", manageFile); | |
} |
Any idea how to control parallel number?
Synchronous version:
const walkSync = (dir, callback) => { const files = fs.readdirSync(dir); files.forEach((file) => { var filepath = path.join(dir, file); const stats = fs.statSync(filepath); if (stats.isDirectory()) { walkSync(filepath, callback); } else if (stats.isFile()) { callback(filepath, stats); } }); };
@acidic9 just curious, is there a reason for a var
on line 4 or it's just an oversight? The rest of places uses const
, just seems like it could've been intentional :)
For fun, here is the ES6/Promises version with an added simple file-type filter:
async walk(dir, ftype) {
let files = await fs.readdir(dir)
files = await Promise.all(files.map(async file => {
const filePath = path.join(dir, file)
const stats = await fs.stat(filePath)
if (stats.isDirectory()) {
return this.walk(filePath, ftype)
} else if (stats.isFile() && file.endsWith(ftype)) {
return filePath
}
}))
// Filter out undefined entries before concatenating
return files.filter(Boolean).reduce((all, folderContents) => all.concat(folderContents), [])
}
Oh, and a minor correction to how you use it. Fairly sure you should have the inner await not just the outer:
for await (const p of await walk(folder, '.html')) {
console.log(p)
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I searched for this a lot of time , Thanks ;)