Get all files recursively in directories NodejS
Solution 1
It looks like the glob
npm package would help you. Here is an example of how to use it:
File hierarchy:
test
├── one.html
└── test-nested
└── two.html
JS code:
const glob = require("glob");
var getDirectories = function (src, callback) {
glob(src + '/**/*', callback);
};
getDirectories('test', function (err, res) {
if (err) {
console.log('Error', err);
} else {
console.log(res);
}
});
which displays:
[ 'test/one.html',
'test/test-nested',
'test/test-nested/two.html' ]
Solution 2
I've seen many very long answers, and it's kinda a waste of memory space. Some also use packages like glob
, but if you don't want to depend on any package, here's my solution.
const Path = require("path");
const FS = require("fs");
let Files = [];
function ThroughDirectory(Directory) {
FS.readdirSync(Directory).forEach(File => {
const Absolute = Path.join(Directory, File);
if (FS.statSync(Absolute).isDirectory()) return ThroughDirectory(Absolute);
else return Files.push(Absolute);
});
}
ThroughDirectory("./input/directory/");
It's pretty self-explanatory. There's an input directory, and it iterates through that. If one of the items is also a directory, go through that and so on. If it's a file, add the absolute path to the array.
Hope this helped :]
Solution 3
Using ES6 yield
const fs = require('fs');
const path = require('path');
function *walkSync(dir) {
const files = fs.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
yield* walkSync(path.join(dir, file.name));
} else {
yield path.join(dir, file.name);
}
}
}
for (const filePath of walkSync(__dirname)) {
console.log(filePath);
}
Solution 4
Here's mine. Like all good answers it's hard to understand:
const isDirectory = path => statSync(path).isDirectory();
const getDirectories = path =>
readdirSync(path).map(name => join(path, name)).filter(isDirectory);
const isFile = path => statSync(path).isFile();
const getFiles = path =>
readdirSync(path).map(name => join(path, name)).filter(isFile);
const getFilesRecursively = (path) => {
let dirs = getDirectories(path);
let files = dirs
.map(dir => getFilesRecursively(dir)) // go through each directory
.reduce((a,b) => a.concat(b), []); // map returns a 2d array (array of file arrays) so flatten
return files.concat(getFiles(path));
};
Solution 5
I really liked Smally's Solution but didn't like the Syntax.
Same solution but slightly easier to read:
const fs = require("fs");
const path = require("path");
let files = [];
const getFilesRecursively = (directory) => {
const filesInDirectory = fs.readdirSync(directory);
for (const file of filesInDirectory) {
const absolute = path.join(directory, file);
if (fs.statSync(absolute).isDirectory()) {
getFilesRecursively(absolute);
} else {
files.push(absolute);
}
}
};
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on February 13, 2022Comments
-
Admin over 2 years
I have a little problem with my function. I would like to get all files in many directories. Currently, I can retrieve the files in the file passed in parameters. I would like to retrieve the html files of each folder in the folder passed as a parameter. I will explain if I put in parameter "test" I retrieve the files in "test" but I would like to retrieve "test / 1 / *. Html", "test / 2 / . /.html ":
var srcpath2 = path.join('.', 'diapo', result); function getDirectories(srcpath2) { return fs.readdirSync(srcpath2).filter(function (file) { return fs.statSync(path.join(srcpath2, file)).isDirectory(); }); }
The result : [1,2,3]
thanks !
-
Admin over 7 yearsthanks ! but how send the result in res.send ? please
-
CodingDefined over 7 years@coco62 Once you get the result inside the function, you can pass that instead of logging it.
-
Vlad about 6 yearsthe shortest way i found
-
loopmode over 4 yearsI had some trouble with typescript+eslint and the flattening of the array in the last lines. So I replaced the last steps by array.reduce. Since we can't post multiline code in comments, here's a single-liner :)
export const getFilesRecursively = (rootPath: string) => getAllSubFolders(rootPath).reduce((result, folder) => [...result, ...getFilesInFolder(folder)], [] as string[])
-
Dara Java almost 4 yearsGood answers are usually the most simple to understand
-
JCraine almost 4 yearsFor me, just running the require crashes nodemon.
-
Asif Ashraf over 3 yearsI was little disappointed that glob will skip Dot Files. What is the purpose of this package if we cannot get dotfiles with simple search?
-
Jared Updike over 3 yearsThis answer is well written and not that hard to understand. It works. It is not a lot of code. It is synchronous, unlike glob.
-
Steven about 3 years@AsifAshraf per the documentation:
You can make glob treat dots as normal characters by setting dot:true in the options.
-- npmjs.com/package/glob -
Siddharth Shyniben about 3 yearsThere's a typo @JCraine. It should be recursive
-
GorvGoyl over 2 yearsnever heard of this syntax and keyword
-
Avin Kavish about 2 yearsInstead of
statSync
now you can load all stats in one call.const dirs = await readdir('./', { withFileTypes: true })
-
Alexey Khachatryan about 2 yearsconst fetchAllFilesFromGivenFolder = (fullPath) => { let files = []; fs.readdirSync(fullPath).forEach(file => { const absolutePath = path.join(fullPath, file); if (fs.statSync(absolutePath).isDirectory()) { const filesFromNestedFolder = fetchAllFilesFromGivenFolder(absolutePath); filesFromNestedFolder.forEach(file => { files.push(file); }) } else return files.push(absolutePath); }); return files }