Skip to content

withFileTypes has different behavior in fs.readdir when reading symbolic directories  #52663

@kylo5aby

Description

@kylo5aby

Version

21.6.0

Platform

Linux 5.15.0-41-generic #44-Ubuntu x86_64 GNU/Linux

Subsystem

fs

What steps will reproduce the bug?

For the directory tree below

dir ├── dir1 │ └── 1.txt └── dir1_s -> dir1

When using fs.readdir or fs.readdirSync to read the contents of dir, there is a difference in the number of contents outputted by the two:

const res = fs.readdirSync('./dir', {recursive: true, withFileTypes: true}); console.log(res); Output: // [ // Dirent { // name: 'dir1', // parentPath: './dir', // path: './dir', // [Symbol(type)]: 2 // }, // Dirent { // name: 'dir1_s', // parentPath: './dir', // path: './dir', // [Symbol(type)]: 3 // }, // Dirent { // name: '1.txt', // parentPath: 'dir/dir1', // path: 'dir/dir1', // [Symbol(type)]: 1 // } // ]
const res = fs.readdirSync('./dir', {recursive: true, withFileTypes: false}); console.log(res); // Output: // [ 'dir1', 'dir1_s', 'dir1/1.txt', 'dir1_s/1.txt' ]

So do fs.readdir.

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

Always

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

No response

What do you see instead?

when withFileTypes: true, the directory entry dir1_s/1.txt haven't been outputted. However, I did not find any description in the documentation regarding the difference in handling symbolic directories between the two.

Additional information

I found that the reason is because the two use different conditions to determine whether to continue traversal. When {withFileTypes:true}. it use

node/lib/fs.js

Line 1420 in 91dc8c9

if (dirent.isDirectory()) {

As described by class Dirent, type "directory" and "symbolic link" of dirent are mutually exclusive.

When {withFileTypes:false}, is use

node/lib/fs.js

Line 1428 in 91dc8c9

const stat = binding.internalModuleStat(resultPath);

Contrary to {withFileTypes:true}, "directory" and "symbolic link" are compatible, and then allows traversal to continue into 1.txt after encountering the symbolic directory dir1_s.

I'm not sure if this is work as expected. If it's not, I believe maintaining consistency with the results of {withFileTypes: false} would be preferable, aligning with the result of find -L [path].

Metadata

Metadata

Assignees

No one assigned

    Labels

    fsIssues and PRs related to the fs subsystem / file system.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions