Skip to content

Stabilize fs.cp(), fs.cpSync(), fsPromises.cp() methods #44598

Description

@theoludwig

What is the problem this feature will solve?

Currently, these methods are marked as Experimental (Stability: 1):

There were no major changes since their introduction in Node.js v16.7.0, so it should be safe to mark them Stable (Stability: 2) as per the Stability index.

If somehow, these methods are still not ready to be stable, this is a tracking issue/roadmap to know what are the needed TODOs before marking them as stable.

What is the feature you are proposing to solve the problem?

Marking fs.cp(), fs.cpSync(), fsPromises.cp() methods as stable (Stability: 2).

For automated test purposes, mocking fs module is a must.
Currently, the most used userland library for that is probably mock-fs, and doesn't support these methods.
Before marking this API stable, Node.js should provide the needed feature(s) for mocking this API in userland, or even better, include mock-fs in Node.js core, this can be well suited with the new test_runner module.

Related issues: tschaub/mock-fs#358, #37746.

What alternatives have you considered?

I think it's best to avoid using experimental APIs, avoid warnings, and simply use features subject to semantic-versioning for easier Node.js upgrades.

The current workaround, I personally use and end up copy/pasting in several projects (too small to be an npm package IMO):

import fs from 'node:fs'
import path from 'node:path'

export const copyDirectory = async (
  source: string,
  destination: string
): Promise<void> => {
  const filesToCreate = await fs.promises.readdir(source)
  for (const file of filesToCreate) {
    const originalFilePath = path.join(source, file)
    const stats = await fs.promises.stat(originalFilePath)
    if (stats.isFile()) {
      const writePath = path.join(destination, file)
      await fs.promises.copyFile(originalFilePath, writePath)
    } else if (stats.isDirectory()) {
      await fs.promises.mkdir(path.join(destination, file))
      await copyDirectory(path.join(source, file), path.join(destination, file))
    }
  }
}

By marking this API as stable, I should be able to use it like this:

import fs from 'node:fs'

await fs.promises.cp(source, destination, { recursive: true })

Activity

  1. added
    fsIssues and PRs related to file-system APIs and the fs module.
    on Sep 11, 2022
  2. aduh95 commented on Sep 15, 2022

    @aduh95
    Contributor

    @nodejs/fs

  3. moved this to Pending Triage in Node.js feature requestson Oct 22, 2022
  4. piedar commented on Oct 25, 2022

    @piedar

    👍 This is a useful API, but the documentation regarding recursive directory copies should be clarified. It currently states

    When copying a directory to another directory, globs are not supported and
    behavior is similar to cp dir1/ dir2/.

    But this is not quite right, as cp -r dir1/ dir2/ copies dir1 into dir2 like ./dir2/dir1/. This command is actually more like cp -r --no-target-directory dir1/ dir2/ which copies the contents of dir1 into dir2.

  5. theoludwig commented on Apr 7, 2023

    @theoludwig
    ContributorAuthor

    Possible to stabilize them before v20? #47381

  6. FStefanni commented on May 25, 2023

    @FStefanni

    Hi,

    just to report a strange behavior, I am not sure if it is intended or a bug.
    When copy a file to a directory:

    fsPromises.cp(
          sourceFile,
          destinationDir,
          {"recursive": true}
    );

    I get this error:

      code: 'ERR_FS_CP_NON_DIR_TO_DIR',
      info: {
        message: 'cannot overwrite non-directory /tmp/my-file.txt with directory /home/myuser',
        path: '/home/myuser',
        syscall: 'cp',
        errno: 20,
        code: 'ENOTDIR'
      },
    

    To fix, I have to use:

    fsPromises.cp(
          sourceFile,
          destinationDir + "/dstFileName.txt",
          {"recursive": true}
    );

    I was expecting a behavior basically as close as possible to the standard bash cp command... This is weird.
    Also, the message seems misleading, since it seems to do the opposite of the intended behavior.

    My node is v20.2.0.

    Regards

  7. github-actions commented on Nov 22, 2023

    @github-actions
    Contributor

    There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

    For more information on how the project manages feature requests, please consult the feature request management document.

  8. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Nov 22, 2023
  9. theoludwig commented on Nov 22, 2023

    @theoludwig
    ContributorAuthor

    Still relevant, as it's still not stable yet.

  10. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Nov 23, 2023
  11. github-actions commented on May 21, 2024

    @github-actions
    Contributor

    There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-stale Issues and PRs exempt from automated stale handling. label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
    For more information on how the project manages feature requests, please consult the feature request management document.

  12. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on May 21, 2024
  13. 3 remaining items

  14. added a commit that references this issue on May 26, 2024
  15. moved this from Awaiting Triage to Done in Node.js feature requestson Jun 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    experimentalIssues and PRs related to experimental features.feature requestIssues requesting new Node.js features.fsIssues and PRs related to file-system APIs and the fs module.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions