node.js rmdir是递归的吗?它会在非空目录上工作吗?

Sam*_*lle 73 node.js

fs.rmdir的文档非常简短,并没有解释当目录不为空时rmdir的行为.

:如果我尝试使用此API删除非空目录会怎样?

Bes*_*esi 95

虽然使用第三方库来做这样的事情,但我无法想出更优雅的解决方案.所以我最终使用了npm-module rimraf.

安装它

npm install rimraf
Run Code Online (Sandbox Code Playgroud)

或者安装它并保存到'package.json'(其他保存选项可以在npm-install文档中找到)

npm install --save rimraf
Run Code Online (Sandbox Code Playgroud)

然后,您可以执行以下操作:

rmdir = require('rimraf');
rmdir('some/directory/with/files', function(error){});
Run Code Online (Sandbox Code Playgroud)

或者在Coffeescript中:

rmdir = require 'rimraf'
rmdir 'some/directory/with/files', (error)->
Run Code Online (Sandbox Code Playgroud)

  • 不需要`require('./ node_modules/rimraf');` - 你可以'require('rimraf');` (5认同)
  • rimraf 已[移植](https://github.com/nodejs/node/pull/29168) 到 Node.js 核心,并且自 Node.js v12.10.0 起 `fs.rmdir` 支持 `recursive` 选项。请参阅[我的答案](/sf/answers/4046373971/)。 (2认同)

gee*_*dew 52

我完全写了这个问题.

我以前的解决方案虽然简单,但不是首选.以下功能是同步解决方案; 虽然异步可能是首选.

deleteFolderRecursive = function(path) {
    var files = [];
    if( fs.existsSync(path) ) {
        files = fs.readdirSync(path);
        files.forEach(function(file,index){
            var curPath = path + "/" + file;
            if(fs.lstatSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
};
Run Code Online (Sandbox Code Playgroud)

[编辑]添加了lstat而不是stat来防止符号链接上的错误

[解决方案]

我的解决方案很容易实现.

var exec = require('child_process').exec,child;
child = exec('rm -rf test',function(err,out) { 
  console.log(out); err && console.log(err); 
});
Run Code Online (Sandbox Code Playgroud)

这个页面很简单,但基本的想法很简单; 在命令行上执行'rm -r'.如果您的应用需要在不同类型的操作系统上运行,请将其放在一个函数中并使用if/else /开关来处理它.

你会想要处理所有的回应; 但这个想法很简单.

  • 这是一个坏主意:你的可移植性很差,而且使用本机可执行文件的黑客攻击总是比使用你的语言的API更危险和敏感. (8认同)
  • 这不是一个好主意.存在`fs.rmdir`,它也无法在Windows上运行. (2认同)
  • 使用`path.join(path,file)`代替`path +“ /” + file` (2认同)

Hen*_*eld 34

简短回答:node.js fs.rmdir()调用POSIX rmdir(); 这将删除一个空目录,或返回错误.在给定的情况下,调用将调用回调函数并将错误作为异常传递.

这里的问题是node.js文档引用POSIX:

Node.js的API文档 文件系统介绍说:

文件I/O由标准POSIX函数的简单包装提供.

这几乎将问题变成了一个副本: 是否有POSIX API /函数列表?

描述fs.rmdir简洁,但足够.

异步rmdir(2).

rmdir(2)这里是为文档的隐式引用rmdir() system call.这里的数字(2)是旧的unix手册页约定,用于指示手册页面的第2部分,包含内核接口.

  • 但是我们如何删除非空目录呢? (63认同)
  • @Markasoftware - 这超出了原始问题的范围,但其他几个答案指向[rimraf](https://github.com/isaacs/rimraf).去看一下. (6认同)
  • 您现在可以使用参数递归调用`rmdir`了:/sf/answers/4050631581/ (2认同)

OOM*_*OOM 10

这对我有用

fs.rmdirSync(folderpath, {recursive: true});
Run Code Online (Sandbox Code Playgroud)

  • 终于发现了。我使用的是温斯顿记录器,不知何故会使日志文件保持打开状态,并会导致这个奇怪的问题。感谢您的快速回复;) (3认同)

rea*_*ice 7

在这一堆答案中只是一个小点,但我认为指出它是好的.

就个人而言(通常)我更愿意使用现有的库(如果有的话)来完成任务.对于我,特别是在开源世界中,采用已有的东西意味着使用和改进已经存在的东西,这可能最终会比我自己做的更好(我正在改进其他一些东西的东西)完成).

在这种情况下,通过一个小搜索,我发现了模块fs-extra,它的目的是替代rimraf并取代需要删除递归目录(显然是使用异步和同步版本).此外,它在github上获得了大量的明星并且似乎目前仍然保留:这两个条件,除了满足需求的事实之外,还为我提供了(几乎一点)的方法.

  • fs-extra不是rimraf的替代品,它包括rimraf.无论如何,我认为fs-extra是一个好主意,我将在我的项目中使用它. (3认同)

Dan*_*tøl 6

从节点 v16 开始,递归fs.rmdir已被弃用。替代品是fs.rm.

与承诺一起使用:

const fs = require("fs/promises")
(async () => {
    await fs.rm("directory", { recursive: true })
})()
Run Code Online (Sandbox Code Playgroud)

传统的:

const fs = require("fs")
fs.rm("directory", { recursive: true }, (err) => {
    // Callback
})
Run Code Online (Sandbox Code Playgroud)

force选项也与此处提及相关,因为如果文件夹丢失,它将防止该方法抛出错误,如果这是为了清理临时文件,这非常有用。

Node.js 文档


Tho*_*enz 5

fs.rmdir不是递归的.

您可以使用像readdirp这样的递归fs.readdir模块来查找所有文件和目录.然后删除所有文件,然后删除所有目录.

对于更简单的解决方案,请查看rimraf.


kim*_*ula 5

Node.js v12.10.0将recursive选项引入了fs.rmdir。由于fs.mkdir自v10.12.0起支持相同的选项,因此可以递归执行创建和删除目录。

$ node --experimental-repl-await

# without recursive option -> error
> await fs.promises.mkdir('foo/bar')
Thrown:
[Error: ENOENT: no such file or directory, mkdir 'foo/bar'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'mkdir',
  path: 'foo/bar'
}

# with recursive option -> success
> await fs.promises.mkdir('foo/bar', { recursive: true })
undefined

# without recursive option -> error
> await fs.promises.rmdir('foo')
Thrown:
[Error: ENOTEMPTY: directory not empty, rmdir 'foo'] {
  errno: -66,
  code: 'ENOTEMPTY',
  syscall: 'rmdir',
  path: 'foo'
}

# with recursive option -> success
> await fs.promises.rmdir('foo', { recursive: true })
undefined
Run Code Online (Sandbox Code Playgroud)