Skip to content

Instantly share code, notes, and snippets.

@kethinov
Created September 22, 2013 09:04
Show Gist options
  • Save kethinov/6658166 to your computer and use it in GitHub Desktop.
Save kethinov/6658166 to your computer and use it in GitHub Desktop.
List all files in a directory in Node.js recursively in a synchronous fashion
// List all files in a directory in Node.js recursively in a synchronous fashion
var walkSync = function(dir, filelist) {
var fs = fs || require('fs'),
files = fs.readdirSync(dir);
filelist = filelist || [];
files.forEach(function(file) {
if (fs.statSync(dir + file).isDirectory()) {
filelist = walkSync(dir + file + '/', filelist);
}
else {
filelist.push(file);
}
});
return filelist;
};
@geenloop
Copy link

I have no idea what you mean but for me it just rendered JSON on server of all files/folders in tree -> send that tree to front-end-> and https://github.com/wix/angular-tree-control just directly render all of that at a glance 👍 but you look like that you need more than that...

@blaasvaer
Copy link

Probably yes. And whenever something contains 'angular' I'm usually out anyway, so ; )

@geenloop
Copy link

yea xD I'm locked in the 2015 year development and ES5 but I'm so grateful for that but depends on everybody's needs ;) good luck anyway

@meowsus
Copy link

meowsus commented Nov 10, 2019

Here's an ES6 refactor. One that applies RegExp filtering:

const fs = require('fs');
const path = require('path');

function findInDir (dir, filter, fileList = []) {
  const files = fs.readdirSync(dir);

  files.forEach((file) => {
    const filePath = path.join(dir, file);
    const fileStat = fs.lstatSync(filePath);

    if (fileStat.isDirectory()) {
      findInDir(filePath, filter, fileList);
    } else if (filter.test(filePath)) {
      fileList.push(filePath);
    }
  });

  return fileList;
}

// Usage
findInDir('./public/audio/', /\.mp3$/);

@MichaelGatesDev
Copy link

@meowsus Your solution works great, thanks.

@konstantin-hatvan
Copy link

Just another implementation

const path = require('path');
const fs = require('fs');

/* Prepend the given path segment */
const prependPathSegment = pathSegment => location => path.join(pathSegment, location);

/* fs.readdir but with relative paths */
const readdirPreserveRelativePath = location => fs.readdirSync(location).map(prependPathSegment(location));

/* Recursive fs.readdir but with relative paths */
const readdirRecursive = location => readdirPreserveRelativePath(location)
    .reduce((result, currentValue) => fs.statSync(currentValue).isDirectory()
        ? result.concat(readdirRecursive(currentValue))
        : result.concat(currentValue), []);

@gemyero
Copy link

gemyero commented Mar 8, 2020

I think the most elegant way to list all files and/or directories recursively is using globs. You can use globby.

const globby = require('globby');

const listAllFilesAndDirs = dir => globby(`${dir}/**/*`);

(async () => {
  const result = await listAllFilesAndDirs(process.cwd());
  console.log(result);
})();

@danilosetubal
Copy link

@gemyero Great solution, thanks!

@SakiiR
Copy link

SakiiR commented Jul 16, 2020

mmh Carefull with globby ;)

Here is my way (with typescript):

import fs from "fs/promises";
import path from "path";

export default async function walk(directory: string) {
  let fileList: string[] = [];

  const files = await fs.readdir(directory);
  for (const file of files) {
    const p = path.join(directory, file);
    if ((await fs.stat(p)).isDirectory()) {
      fileList = [...fileList, ...(await walk(p))];
    } else {
      fileList.push(p);
    }
  }

  return fileList;
}

@ariassd
Copy link

ariassd commented Dec 8, 2020

Alternative solution in Just two lines, Just for fun and learning

const path = ''; // 👈 path to your location
const list = require("child_process").execSync(`cd ${path} && ls -R`).toString().split(`\n`);

⚠️ IMPORTANT
Be careful, this solution use a bash script and it works fine in MACOS, for windows or linux could be different

@kiuKisas
Copy link

kiuKisas commented Feb 18, 2021

What I use is based on @vidul-nikolaev-petrov version, with a callback argument to do something with files:

const walkSync = (dir, callback) =>  fs.lstatSync(dir).isDirectory()
        ? fs.readdirSync(dir).map(f => walkSync(path.join(dir, f), callback))
        : callback(dir);

// Note: call to flat at the end to have one array with every paths
const svgs = walkSync(path, fileToBase64).flat()

@SakiiR
Copy link

SakiiR commented Feb 18, 2021

Alternative solution in Just two lines, Just for fun and learning

const path = ''; // 👈 path to your location
const list = require("child_process").execSync(`cd ${path} && ls -R`).toString().split(`\n`);

⚠️ IMPORTANT
Be careful, this solution use a bash script and it works fine in MACOS, for windows or linux could be different

Please, never do that

@Aleksandar1932
Copy link

@JESUSrosetolife
Copy link

Hi, here's a modern version:

const fs = require('fs').promises;
const path = require('path');

const walk = async (dir, filelist = []) => {
  const files = await fs.readdir(dir);

  for (file of files) {
    const filepath = path.join(dir, file);
    const stat = await fs.stat(filepath);

    if (stat.isDirectory()) {
      filelist = await walk(filepath, filelist);
    } else {
      filelist.push(file);
    }
  }

  return filelist;
}

Here's what I used (needed import)

import * as fs from 'fs/promises';
import path from 'path';

export async function directory_read(dir, filelist = []) {
  const files = await fs.readdir(dir);

  for (let file of files) {
    const filepath = path.join(dir, file);
    const stat = await fs.stat(filepath);

    if (stat.isDirectory()) {
      filelist = await directory_read(filepath, filelist);
    } else {
      filelist.push(file);
    }
  }

  return filelist;
}

@schadocalex
Copy link

schadocalex commented Oct 12, 2023

Node v20.1+

const filelist = await fs.readdir(dir, { recursive: true });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment