Looping through files in a folder Node.JS Looping through files in a folder Node.JS arrays arrays

Looping through files in a folder Node.JS


Older answer with callbacks

You want to use the fs.readdir function to get the directory contents and the fs.rename function to actually do the renaming. Both these functions have synchronous versions if you need to wait for them to finishing before running the code afterwards.

I wrote a quick script that does what you described.

var fs = require('fs');var path = require('path');// In newer Node.js versions where process is already global this isn't necessary.var process = require("process");var moveFrom = "/home/mike/dev/node/sonar/moveme";var moveTo = "/home/mike/dev/node/sonar/tome"// Loop through all the files in the temp directoryfs.readdir(moveFrom, function (err, files) {  if (err) {    console.error("Could not list the directory.", err);    process.exit(1);  }  files.forEach(function (file, index) {    // Make one pass and make the file complete    var fromPath = path.join(moveFrom, file);    var toPath = path.join(moveTo, file);    fs.stat(fromPath, function (error, stat) {      if (error) {        console.error("Error stating file.", error);        return;      }      if (stat.isFile())        console.log("'%s' is a file.", fromPath);      else if (stat.isDirectory())        console.log("'%s' is a directory.", fromPath);      fs.rename(fromPath, toPath, function (error) {        if (error) {          console.error("File moving error.", error);        } else {          console.log("Moved file '%s' to '%s'.", fromPath, toPath);        }      });    });  });});

Tested on my local machine.

node testme.js '/home/mike/dev/node/sonar/moveme/hello' is a file.'/home/mike/dev/node/sonar/moveme/test' is a directory.'/home/mike/dev/node/sonar/moveme/test2' is a directory.'/home/mike/dev/node/sonar/moveme/test23' is a directory.'/home/mike/dev/node/sonar/moveme/test234' is a directory.Moved file '/home/mike/dev/node/sonar/moveme/hello' to '/home/mike/dev/node/sonar/tome/hello'.Moved file '/home/mike/dev/node/sonar/moveme/test' to '/home/mike/dev/node/sonar/tome/test'.Moved file '/home/mike/dev/node/sonar/moveme/test2' to '/home/mike/dev/node/sonar/tome/test2'.Moved file '/home/mike/dev/node/sonar/moveme/test23' to '/home/mike/dev/node/sonar/tome/test23'.Moved file '/home/mike/dev/node/sonar/moveme/test234' to '/home/mike/dev/node/sonar/tome/test234'.

Update: fs.promises functions with async/await

Inspired by ma11hew28's answer (shown here), here is the same thing as above but with the async functions in fs.promises. As noted by ma11hew28, this may have memory limitations versus fs.promises.opendir added in v12.12.0.

Quick code below.

//jshint esversion:8//jshint node:trueconst fs = require( 'fs' );const path = require( 'path' );const moveFrom = "/tmp/movefrom";const moveTo = "/tmp/moveto";// Make an async function that gets executed immediately(async ()=>{    // Our starting point    try {        // Get the files as an array        const files = await fs.promises.readdir( moveFrom );        // Loop them all with the new for...of        for( const file of files ) {            // Get the full paths            const fromPath = path.join( moveFrom, file );            const toPath = path.join( moveTo, file );            // Stat the file to see if we have a file or dir            const stat = await fs.promises.stat( fromPath );            if( stat.isFile() )                console.log( "'%s' is a file.", fromPath );            else if( stat.isDirectory() )                console.log( "'%s' is a directory.", fromPath );            // Now move async            await fs.promises.rename( fromPath, toPath );            // Log because we're crazy            console.log( "Moved '%s'->'%s'", fromPath, toPath );        } // End for...of    }    catch( e ) {        // Catch anything bad that happens        console.error( "We've thrown! Whoops!", e );    }})(); // Wrap in parenthesis and call now


fs.readdir(path[, options], callback) (which Mikey A. Leonetti used in his answer) and its variants (fsPromises.readdir(path[, options]) and fs.readdirSync(path[, options])) each reads all of a directory's entries into memory at once. That's good for most cases, but if the directory has very many entries and/or you want to lower your application's memory footprint, you could instead iterate over the directory's entries one at a time.

Asynchronously

Directories are async iterable, so you could do something like this:

const fs = require('fs')async function ls(path) {  const dir = await fs.promises.opendir(path)  for await (const dirent of dir) {    console.log(dirent.name)  }}ls('.').catch(console.error)

Or, you could use dir.read() and/or dir.read(callback) directly.

Synchronously

Directories aren't sync iterable, but you could use dir.readSync() directly. For example:

const fs = require('fs')const dir = fs.opendirSync('.')let direntwhile ((dirent = dir.readSync()) !== null) {  console.log(dirent.name)}dir.closeSync()

Or, you could make directories sync iterable. For example:

const fs = require('fs')function makeDirectoriesSyncIterable() {  const p = fs.Dir.prototype  if (p.hasOwnProperty(Symbol.iterator)) { return }  const entriesSync = function* () {    try {      let dirent      while ((dirent = this.readSync()) !== null) { yield dirent }    } finally { this.closeSync() }  }  if (!p.hasOwnProperty(entriesSync)) { p.entriesSync = entriesSync }  Object.defineProperty(p, Symbol.iterator, {    configurable: true,    enumerable: false,    value: entriesSync,    writable: true  })}makeDirectoriesSyncIterable()

And then, you could do something like this:

const dir = fs.opendirSync('.')for (const dirent of dir) {  console.log(dirent.name)}

Note: "In busy processes, use the asynchronous versions of these calls. The synchronous versions will block the entire process until they complete, halting all connections."

References:


Read all folders in a directory

  const readAllFolder = (dirMain) => {  const readDirMain = fs.readdirSync(dirMain);  console.log(dirMain);  console.log(readDirMain);  readDirMain.forEach((dirNext) => {    console.log(dirNext, fs.lstatSync(dirMain + "/" + dirNext).isDirectory());    if (fs.lstatSync(dirMain + "/" + dirNext).isDirectory()) {      readAllFolder(dirMain + "/" + dirNext);    }   });};