nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
106.54k stars 29.04k forks source link

readdirSync cannot read files properly when using { recursive: true, withFileTypes: true } #51773

Open prfd opened 7 months ago

prfd commented 7 months ago

Version

v18.17.1

Platform

No response

Subsystem

fs

What steps will reproduce the bug?

mkdir -p test/include
touch test/libvips-cpp.so.42
const fs = require('fs');
fs.readdirSync('test', {recursive: true, withFileTypes: true});

How often does it reproduce? Is there a required condition?

No response

What is the expected behavior? Why is that the expected behavior?

await fs.promises.readdir('test', {recursive: true, withFileTypes: true})
[
  Dirent { name: 'include', path: 'folder', [Symbol(type)]: 2 },
  Dirent {
    name: 'libvips-cpp.so.42',
    path: 'folder',
    [Symbol(type)]: 1
  }
]

What do you see instead?

[
  Dirent { name: 'include', path: 'folder', [Symbol(type)]: 2 },
  Dirent {
    name: 'libvips-cpp.so.42',
    path: 'folder',
    [Symbol(type)]: 1
  },
  Dirent {
    name: undefined,
    path: 'folder/include',
    [Symbol(type)]: undefined
  },
  Dirent {
    name: undefined,
    path: 'folder/include',
    [Symbol(type)]: undefined
  }
]

Additional information

No response

richardlau commented 7 months ago

Can reproduce in 18.17.1 but not in 18.19.0:

$ nvm run 18.17.1
Running node v18.17.1 (npm v9.6.7)
Welcome to Node.js v18.17.1.
Type ".help" for more information.
> const fs = require('fs');
undefined
> fs.readdirSync('test', {recursive: true, withFileTypes: true});
[
  Dirent { name: 'include', path: 'test', [Symbol(type)]: 2 },
  Dirent { name: 'libvips-cpp.so.42', path: 'test', [Symbol(type)]: 1 },
  Dirent {
    name: undefined,
    path: 'test/include',
    [Symbol(type)]: undefined
  },
  Dirent {
    name: undefined,
    path: 'test/include',
    [Symbol(type)]: undefined
  }
]
>
$ nvm run 18.19.0
Running node v18.19.0 (npm v10.2.3)
Welcome to Node.js v18.19.0.
Type ".help" for more information.
> const fs = require('fs');
undefined
> fs.readdirSync('test', {recursive: true, withFileTypes: true});
[
  Dirent { name: 'include', path: 'test', [Symbol(type)]: 2 },
  Dirent { name: 'libvips-cpp.so.42', path: 'test', [Symbol(type)]: 1 }
]
>
richardlau commented 7 months ago

Probably related to https://github.com/nodejs/node/issues/48858 https://github.com/nodejs/node/pull/48698 was included in Node.js 18.19.0.

prfd commented 7 months ago

Probably related to #48858 #48698 was included in Node.js 18.19.0.

So, all stable versions of electron have a broken readdirSync, that's unfortunate.

https://releases.electronjs.org/

richardlau commented 7 months ago

Probably related to #48858 #48698 was included in Node.js 18.19.0.

So, all stable versions of electron have a broken readdirSync, that's unfortunate.

https://releases.electronjs.org/

You'll need to discuss that with Electron as we don't control what versions of Node.js they use.

ankit142 commented 7 months ago

Try the async approach:

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

async function listDirectoryRecursive(directory) {
    try {
        const dirents = await fs.readdir(directory, { withFileTypes: true });
        for (const dirent of dirents) {
            console.log(dirent);
            if (dirent.isDirectory()) {
                await listDirectoryRecursive(`${directory}/${dirent.name}`);
            }
        }
    } catch (error) {
        console.error('Error reading directory:', error);
    }
}

listDirectoryRecursive('test');