How do you get a list of the names of all files present in a directory in Node.js?

1,318,765

Solution 1

You can use the fs.readdir or fs.readdirSync methods. fs is included in Node.js core, so there's no need to install anything.

fs.readdir

const testFolder = './tests/';
const fs = require('fs');

fs.readdir(testFolder, (err, files) => {
  files.forEach(file => {
    console.log(file);
  });
});

fs.readdirSync

const testFolder = './tests/';
const fs = require('fs');

fs.readdirSync(testFolder).forEach(file => {
  console.log(file);
});

The difference between the two methods, is that the first one is asynchronous, so you have to provide a callback function that will be executed when the read process ends.

The second is synchronous, it will return the file name array, but it will stop any further execution of your code until the read process ends.

Solution 2

IMO the most convenient way to do such tasks is to use a glob tool. Here's a glob package for node.js. Install with

npm install glob

Then use wild card to match filenames (example taken from package's website)

var glob = require("glob")

// options is optional
glob("**/*.js", options, function (er, files) {
  // files is an array of filenames.
  // If the `nonull` option is set, and nothing
  // was found, then files is ["**/*.js"]
  // er is an error object or null.
})

If you are planning on using globby here is an example to look for any xml files that are under current folder

var globby = require('globby');

const paths = await globby("**/*.xml");  

Solution 3

The answer above does not perform a recursive search into the directory though. Here's what I did for a recursive search (using node-walk: npm install walk)

var walk    = require('walk');
var files   = [];

// Walker options
var walker  = walk.walk('./test', { followLinks: false });

walker.on('file', function(root, stat, next) {
    // Add this file to the list of files
    files.push(root + '/' + stat.name);
    next();
});

walker.on('end', function() {
    console.log(files);
});

Solution 4

Get files in all subdirs

const fs=require('fs');

function getFiles (dir, files_){
    files_ = files_ || [];
    var files = fs.readdirSync(dir);
    for (var i in files){
        var name = dir + '/' + files[i];
        if (fs.statSync(name).isDirectory()){
            getFiles(name, files_);
        } else {
            files_.push(name);
        }
    }
    return files_;
}

console.log(getFiles('path/to/dir'))

Solution 5

As of Node v10.10.0, it is possible to use the new withFileTypes option for fs.readdir and fs.readdirSync in combination with the dirent.isDirectory() function to filter for filenames in a directory. That looks like this:

fs.readdirSync('./dirpath', {withFileTypes: true})
.filter(item => !item.isDirectory())
.map(item => item.name)

The returned array is in the form:

['file1.txt', 'file2.txt', 'file3.txt']
Share:
1,318,765
resopollution
Author by

resopollution

Updated on May 03, 2022

Comments

  • resopollution
    resopollution about 2 years

    I'm trying to get a list of the names of all the files present in a directory using Node.js. I want output that is an array of filenames. How can I do this?

  • Eraden
    Eraden about 12 years
    fs.readdirSync is better, native alternative created specially for this.
  • Ruben Tan
    Ruben Tan about 12 years
    fs.readdirSync doesn't walk into sub directories unfortunately, unless you are willing to write your own routine to do just that, which you don't given that there are already npm modules out there to solve this very problem.
  • Rob W
    Rob W about 12 years
    Note: readdir also shows directory names. To filter these, use fs.stat(path, callback(err, stats)) and stats.isDirectory().
  • santiagoIT
    santiagoIT almost 12 years
    Here is a link to the walk github repo + docs: github.com/coolaj86/node-walk
  • Pogrindis
    Pogrindis over 9 years
    this was the best solution for me as i wanted to specify filetype easier than string comparisons. Thanks.
  • jkutianski
    jkutianski over 9 years
    Why if (typeof files_ === 'undefined') files_=[];? you only need to do var files_ = files_ || []; instead of files_ = files_ || [];.
  • GFoley83
    GFoley83 about 9 years
    You forgot to add var fs = require('fs'); at the start of getFiles.
  • user2867288
    user2867288 almost 9 years
    Get into the habit of adding semicolons to the end of your statements. You can't minify code otherwise. Nevertheless, thanks for the much needed async contribution.
  • Igwe Kalu
    Igwe Kalu almost 9 years
    OP did not ask about which API does a recursive read. In any case, the accepted answer provides what can also serve as a basis for making a recursive read.
  • jcollum
    jcollum almost 9 years
    I like this one too just because globbing is almost a fundamental skill in node. If you want to just get filenames back, pass in a cwd in the options object.
  • DragonKnight
    DragonKnight over 8 years
    I should add that most probably you should go with readdire because you dont want to block IO in node.
  • A T
    A T over 8 years
    I added an excludeDirs array argument also. It changes it enough so that maybe you should edit it instead (if you want it). Otherwise I'll add it in a different answer. gist.github.com/AlecTaylor/f3f221b4fb86b4375650
  • Hunan Rostomyan
    Hunan Rostomyan over 8 years
    @AT Nice! You should post your own answer, as it's a useful extension. Let's keep this one featureless.
  • MIDE11
    MIDE11 over 8 years
    Should replace the line in walkSync from walk(filePath, callback); to walkSync(filePath, callback);
  • Lanti
    Lanti over 8 years
    How can get the results of glob outside of itself? Eg. I want to console.log the results, but not inside glob()?
  • r3wt
    r3wt about 8 years
    @user3705055 unless you're using gulp to read in a directory of source order dependant files and compile them into a single executable.
  • SalahAdDin
    SalahAdDin about 8 years
    I have a main folder: scss, and inside it other folder: themes, but the final list give me all directories, not only directories without exclude directorie, whats happen?
  • SalahAdDin
    SalahAdDin about 8 years
    Only works fine with '.' folder directory, with the rest directories doesn't works.
  • j_d
    j_d about 8 years
    This is a fantastic function. Quick question: is there a quick way to ignore certain dirs? I want to ignore directories starting with .git
  • Evan Carroll
    Evan Carroll about 8 years
  • Evan Carroll
    Evan Carroll about 8 years
  • Glenn Lawrence
    Glenn Lawrence about 8 years
    @Lanti: The glob.sync(pattern, [options]) method may be easier to use as it simply returns an array of file names, rather than using a callback. More info here: github.com/isaacs/node-glob
  • DifferentPseudonym
    DifferentPseudonym about 8 years
    But you're still using fs.statSync, which blocks, in async version. Shouldn't you be using fs.stat instead?
  • Danny Tuppeny
    Danny Tuppeny over 7 years
    > unless you are willing to write your own routine to do just that, which you don't given that there are already npm modules out there to solve this very problem Yeah, you don't want to write left-pad yourself too when there's a package for that! :/
  • adnan
    adnan about 7 years
    fs.walk is removed from fs-promise as it it not supported by fs ( github.com/kevinbeaty/fs-promise/issues/28 )
  • Sancarn
    Sancarn about 7 years
    I'm confused... Wouldn't it be better to use ls or dir /b/s for this job? Would have thought these methods would be much faster than iterating in Node...
  • Radon Rosborough
    Radon Rosborough almost 7 years
    @Sancarn You want to try parsing the output of ls? Just wait until somebody creates some filenames with embedded spaces and newlines…
  • Sancarn
    Sancarn almost 7 years
    @RadonRosborough yeah recently found out that ls isn't really good for file lists. But find is pretty good at it :)
  • Nacho Coloma
    Nacho Coloma over 6 years
    For people like me looking for a glob implementation using Promises, check out globby by sindresorhus: github.com/sindresorhus/globby
  • bnp887
    bnp887 over 5 years
    As of Node v10.10.0, a combination of the withFileTypes option for the readdir and readdirSync functions and the isDirectory() method can be used to filter just the files in the directory - docs and an example here
  • user2867288
    user2867288 over 5 years
    HAHAHAHA that's not part of the spec, just some random person calling their preferred linting style "standardjs". Semicolons are good practice especially in Javascript to maintain code clarity. Otherwise you and your team must memorize the rules of automatic semicolon insertion, and I know at least the average JS developer where I work is not that diligent.
  • mjsarfatti
    mjsarfatti about 5 years
    Worked great for me AND it's recursive. Just remember that the import syntax is still behind a flag in Node, you might have to go the old way: const fs = require('fs');
  • Saravanan Rajaraman
    Saravanan Rajaraman about 5 years
    I like this one.
  • douira
    douira over 4 years
    @user2867288 But since ASI exists, we can use it, no? I use eslint and prettier to format my code on save regularly and semicolon insertion is a non-issue.
  • Md Mazedul Islam Khan
    Md Mazedul Islam Khan over 4 years
    @Josh It works like charm. However, having a bit of difficulty to understand how the [...files, ...getAllFiles(name)] or [...files, name] works. A bit of explanation would be very helpful :)
  • Val Redchenko
    Val Redchenko over 4 years
    this is what people are searching for in 2020 - should be "pinned"
  • T90
    T90 over 4 years
    @MdMazedulIslamKhan The ... used here is called a spread syntax. What it basically does is takes all objects inside the array and 'spreads' it into the new array. In this case, all entries inside the files array is added to the return along with all the values returned from the recursive call. YOu can refer to the spread syntax here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • Mathias Lykkegaard Lorenzen
    Mathias Lykkegaard Lorenzen about 4 years
    This is a recursive method. It does not support very deep folder structures, which will result in a Stack Overflow.
  • KyleMit
    KyleMit almost 4 years
    @justmaier & a.barbieri - thanks for the code and answer!
  • mesqueeb
    mesqueeb almost 4 years
    You have the problem where path is the name of your imported require('path') but then you re-define const path inside the function... This is really confusing and might lead to bugs!
  • Aakash
    Aakash over 3 years
    hi if i want to show folder as well so what should i do ? like ` [ "/animals/all.jpg", "/animals/mammals" "/animals/mammals/cat.jpg", "/animals/mammals/dog.jpg", "/animals/insects/bee.jpg" ]; ` any solution
  • a.barbieri
    a.barbieri about 3 years
    Hi @Aakash, try adding files.unshift(dir) berfore the last return of the async function. Anyway it'd be best if you could create a new question as it might help other people with the same need and receive better feedback. ;-)
  • Aakash
    Aakash about 3 years
    hi @a.barbieri what if i want to read only starting 2 level folder what i have to do for ex: my directory look like this animals/mammals/name and i want to stop at mammal by providing some depth [ "/animals/all.jpg", "/animals/mammals/cat.jpg", "/animals/mammals/dog.jpg", "/animals/insects/bee.jpg" ];
  • WhoIsCarlo
    WhoIsCarlo about 3 years
    Thanks for this!
  • a.barbieri
    a.barbieri about 3 years
    Please create a new question and copy/paste the link it here in the comments. I'll be happy to answer.
  • Mauricio Gracia Gutierrez
    Mauricio Gracia Gutierrez about 3 years
    I have updated the answer with @NachoColoma coment and showing how to use it
  • Radvylf Programs
    Radvylf Programs about 3 years
    @MathiasLykkegaardLorenzen If you've got a file system nested 11k directories deep you've probably got a lot of other things to worry about :p
  • Mathias Lykkegaard Lorenzen
    Mathias Lykkegaard Lorenzen about 3 years
    It doesn't have to be 11k. It depends on how much is put on the stack, and this method has quite large allocations to the stack.
  • Admin
    Admin about 3 years
    If i need to read sub directories I mean to say recursive then how can fs-extra is useful @LondonGuy
  • Byusa
    Byusa about 3 years
    How would you do this in Typescript? I get this error when I try to do in typescript: "TypeError: fs.readdir is not a function" Any help is appreciated.
  • Tyler2P
    Tyler2P over 2 years
    Could you provide more details on what the code does and how it helps the OP?
  • Cesar Morillas
    Cesar Morillas over 2 years
    It simply gets an array of file names from some path. Only names of files, not subdirectory names.
  • Dr.jacky
    Dr.jacky over 2 years
    @RubenTan How to check the filetype? Cause it lists hidden files too. On mac: .DS_Store, for example.
  • Dr.jacky
    Dr.jacky over 2 years
    In the readdirSync I push the file into my array I defined in first line of the class. In the readdirSync the array size is 1 but, out of that scope, the size is 0!
  • Kaushik R Bangera
    Kaushik R Bangera about 2 years
    And 2022 as well!