
There are two similar but distinct modules that can be used to list files and directories in Node.js.
- fs.readdir (asynchronous) (this article)
- fs.readdirSync (synchronous)
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