Bootstrap FreeKB - Node.js - List files in a directory using fs.readdir
Node.js - List files in a directory using fs.readdir

Updated:   |  Node.js articles

There are two similar but distinct modules that can be used to list files and directories in Node.js.

fs.readdir can be used to list the files and directories in a directory. In this example, the files and directories in the /tmp directory will be stored in a list named "files_and_directories" 

const fs = require("fs")

fs.readdir('/tmp/', (err, files_and_directories) => {
  console.log(files_and_directories)
  console.error(err)
})

 

Be aware that if you are using a Node.js module instead of CommonJS, you will have "type": "module" in package.json. In this scenario, you will use import instead of require.

import fs from "fs"

 

Something like this should be returned.

[
  '.hidden_file',
  '.hidden_directory',
  'my_directory',
  'foo.txt',
  'bar.txt'
]
null

 

Almost always, you probably want an if / else statement to determine if there was some error.

import fs from "fs"

fs.readdir('/tmp/', (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    console.log(files_and_directories)
  }
})

 

fs.readdir is asynchronous where fs.readdirSync is not asynchronous. For example, let's say the /tmp/foo directory contains thousands of files and sub-directories and /tmp/bar only contains a few files. With fs.readdirSync (not asynchronous) the first block that gets all of the files and subdirectories in /tmp/foo must complete before moving onto the next block and gets the files in the /tmp/bar directory.

import fs from "fs"

fs.readdir('/tmp/foo', (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    console.log(files_and_directories)
  }
})

fs.readdir('/tmp/bar', (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    console.log(files_and_directories)
  }
})

 

The output from fs.readdirSync (not asynchronous) would be something like this, where the first list will be all of the files and sub-directories in /tmp/foo and the second list will be the files in /tmp/bar.

[
  '0.txt',  '1.txt',  '10.txt', '11.txt', '12.txt', '13.txt',
  '14.txt', '15.txt', '16.txt', '17.txt', '18.txt', '19.txt',
  '2.txt',  '20.txt', '21.txt', '22.txt', '23.txt', '24.txt',
  '25.txt', '26.txt', '27.txt', '28.txt', '29.txt', '3.txt',
  '30.txt', '31.txt', '32.txt', '33.txt', '34.txt', '35.txt',
  '36.txt', '37.txt', '38.txt', '39.txt', '4.txt',  '40.txt',
  '41.txt', '42.txt', '43.txt', '44.txt', '45.txt', '46.txt',
  '47.txt', '48.txt', '49.txt', '5.txt',  '50.txt', '51.txt',
  '52.txt', '53.txt', '54.txt', '55.txt', '56.txt', '57.txt',
  '58.txt', '59.txt', '6.txt',  '60.txt', '61.txt', '62.txt',
  '63.txt', '64.txt', '65.txt', '66.txt', '67.txt', '68.txt',
  '69.txt', '7.txt',  '70.txt', '71.txt', '72.txt', '73.txt',
  '74.txt', '75.txt', '76.txt', '77.txt', '78.txt', '79.txt',
  '8.txt',  '80.txt', '81.txt', '82.txt', '83.txt', '84.txt',
  '85.txt', '86.txt', '87.txt', '88.txt', '89.txt', '9.txt',
  '90.txt', '91.txt', '92.txt', '93.txt', '94.txt', '95.txt',
  '96.txt', '97.txt', '98.txt', '99.txt',
  ... 9999 more items
]
[ 'hello.txt', 'world.txt' ]

 

On the other hand, fs.readdir (asynchronous) would probably first return the files in the /tmp/bar directory because it should take much less time for this block to complete and then the list of files and sub-directories in the /tmp/foo directory would come next.

[ 'hello.txt', 'world.txt' ]
[
  '0.txt',  '1.txt',  '10.txt', '11.txt', '12.txt', '13.txt',
  '14.txt', '15.txt', '16.txt', '17.txt', '18.txt', '19.txt',
  '2.txt',  '20.txt', '21.txt', '22.txt', '23.txt', '24.txt',
  '25.txt', '26.txt', '27.txt', '28.txt', '29.txt', '3.txt',
  '30.txt', '31.txt', '32.txt', '33.txt', '34.txt', '35.txt',
  '36.txt', '37.txt', '38.txt', '39.txt', '4.txt',  '40.txt',
  '41.txt', '42.txt', '43.txt', '44.txt', '45.txt', '46.txt',
  '47.txt', '48.txt', '49.txt', '5.txt',  '50.txt', '51.txt',
  '52.txt', '53.txt', '54.txt', '55.txt', '56.txt', '57.txt',
  '58.txt', '59.txt', '6.txt',  '60.txt', '61.txt', '62.txt',
  '63.txt', '64.txt', '65.txt', '66.txt', '67.txt', '68.txt',
  '69.txt', '7.txt',  '70.txt', '71.txt', '72.txt', '73.txt',
  '74.txt', '75.txt', '76.txt', '77.txt', '78.txt', '79.txt',
  '8.txt',  '80.txt', '81.txt', '82.txt', '83.txt', '84.txt',
  '85.txt', '86.txt', '87.txt', '88.txt', '89.txt', '9.txt',
  '90.txt', '91.txt', '92.txt', '93.txt', '94.txt', '95.txt',
  '96.txt', '97.txt', '98.txt', '99.txt',
  ... 9999 more items
]

 

In Node.js version 20 and above, recursive: true can be used to do a recursive search for all files and directories at and below the base target directory.

import fs from "fs"

fs.readdir('/tmp/', {recursive: true}, (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    console.log(files_and_directories)
  }
})

 

forEach can be used to loop through the list.

import fs from "fs"

fs.readdir(base_directory, (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    files_and_directories.forEach(item => {
      console.log(item)
    })
  }
})

 

Here is how you could append the files and directories to a list named files_and_directories_list.

const base_directory = '/tmp'

const files_and_directories_list = []

fs.readdir(base_directory, {recursive: true}, (err, files_and_directories) => {
  if (err) {
    console.error(err)
  } else {
    files_and_directories.forEach(item => {
      files_and_directories_list.push(base_directory + '/' + item))
    })
  }
})

console.log(files_and_directories_list)

 

fs.lstat can be used to return the stats of each item to determine if the item . . . 

  • isFile()
  • isDirectory()
  • isSymbolicLink()
  • isFIFO()
  • isSocket()
  • isCharacterDevice()
  • isBlockDevice()

For example, this will append only files to the files_lists.

const base_directory = '/tmp'

const files_list = []

fs.readdir(base_directory, {recursive: true}, (err, files_and_directories_callback) => {
  if (err) {
    console.error(err)
  } else {
    files_and_directories_callback.forEach(item => {
      const absolute_path = base_directory + '/' + item
      fs.lstat(absolute_path, (stats_err, stats_callback) => {
        if (stats_err) {
          console.error(stats_err)
        } else {
          if (stats_callback.isFile()) {
            files_list.push(absolute_path)
          }
        }
      })
    })
  }
})

console.log(files_list)

 

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter aef151 in the box below so that we can be sure you are a human.