在我的节点应用程序中,我需要删除一个目录,其中有一些文件,但fs。Rmdir只适用于空目录。我该怎么做呢?
当前回答
我通常不复活旧线程,但这里有很多关于搅动和没有rimraf的答案,这些对我来说似乎都太复杂了。
首先,在现代Node (>= v8.0.0)中,你可以只使用节点核心模块来简化过程,完全异步,并在5行函数中并行化文件的解链接,并且仍然保持可读性:
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const readdir = promisify(fs.readdir);
const rmdir = promisify(fs.rmdir);
const unlink = promisify(fs.unlink);
exports.rmdirs = async function rmdirs(dir) {
let entries = await readdir(dir, { withFileTypes: true });
await Promise.all(entries.map(entry => {
let fullPath = path.join(dir, entry.name);
return entry.isDirectory() ? rmdirs(fullPath) : unlink(fullPath);
}));
await rmdir(dir);
};
另一方面,路径遍历攻击的保护不适合此函数,因为
It is out of scope based on the Single Responsibility Principle. Should be handled by the caller not this function. This is akin to the command-line rm -rf in that it takes an argument and will allow the user to rm -rf / if asked to. It would be the responsibility of a script to guard not the rm program itself. This function would be unable to determine such an attack since it does not have a frame of reference. Again that is the responsibility of the caller who would have the context of intent which would provide it a reference to compare the path traversal. Sym-links are not a concern as .isDirectory() is false for sym-links and are unlinked not recursed into.
最后但并非最不重要的是,有一种罕见的竞争条件,即在运行递归时,如果在正确的时间在脚本之外取消链接或删除其中一个条目,则递归可能会出错。由于这种情况在大多数环境中并不典型,因此可能会被忽略。然而,如果需要(对于一些边缘情况),这个问题可以通过下面这个稍微复杂一点的例子来缓解:
exports.rmdirs = async function rmdirs(dir) {
let entries = await readdir(dir, { withFileTypes: true });
let results = await Promise.all(entries.map(entry => {
let fullPath = path.join(dir, entry.name);
let task = entry.isDirectory() ? rmdirs(fullPath) : unlink(fullPath);
return task.catch(error => ({ error }));
}));
results.forEach(result => {
// Ignore missing files/directories; bail on other errors
if (result && result.error.code !== 'ENOENT') throw result.error;
});
await rmdir(dir);
};
编辑:使isDirectory()成为一个函数。最后删除实际目录。修复丢失的递归。
其他回答
截至节点v14(2020年10月),fs模块有fs。rm和rs.rmSync支持递归非空目录解链接:
https://nodejs.org/docs/latest-v14.x/api/fs.html#fs_fs_rm_path_options_callback
所以你现在可以这样做:
const fs = require('fs');
fs.rm('/path/to/delete', { recursive: true }, () => console.log('done'));
or:
const fs = require('fs');
fs.rmSync('/path/to/delete', { recursive: true });
console.log('done');
同步删除文件夹
const fs = require('fs');
const Path = require('path');
const deleteFolderRecursive = function (directoryPath) {
if (fs.existsSync(directoryPath)) {
fs.readdirSync(directoryPath).forEach((file, index) => {
const curPath = path.join(directoryPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
// recurse
deleteFolderRecursive(curPath);
} else {
// delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(directoryPath);
}
};
解释
从Node.js v14开始,我们现在可以使用require("fs").promises。Rm函数使用promise删除文件。第一个参数是要删除的文件或文件夹(即使是不存在的文件或文件夹)。您可以在第二个参数的对象中使用递归和强制选项来模拟rm Shell命令实用程序的-rf选项的行为。
例子
"use strict";
require("fs").promises.rm("directory", {recursive: true, force: true}).then(() => {
console.log("removed");
}).catch(error => {
console.error(error.message);
});
See
Node.js v14文档
Mozilla开发者承诺文档
Rm命令手册
只需使用rmdir模块!这很简单。
const fs = require("fs")
const path = require("path")
let _dirloc = '<path_do_the_directory>'
if (fs.existsSync(_dirloc)) {
fs.readdir(path, (err, files) => {
if (!err) {
for (let file of files) {
// Delete each file
fs.unlinkSync(path.join(_dirloc, file))
}
}
})
// After the 'done' of each file delete,
// Delete the directory itself.
if (fs.unlinkSync(_dirloc)) {
console.log('Directory has been deleted!')
}
}
推荐文章
- DeprecationWarning:当我将脚本移动到另一个服务器时,由于安全性和可用性问题,Buffer()已弃用
- 我如何确定正确的“max-old-space-size”为Node.js?
- npm犯错!代码UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- Access-Control-Allow-Origin不允许Origin < Origin >
- 如何获得所有已注册的快捷路线?
- 你可以为你的组织托管一个私有的存储库来使用npm吗?
- 如何定位父文件夹?
- Gulp命令未找到-安装Gulp后错误
- 在Node.js中写入文件时创建目录
- 如何将自定义脚本添加到包中。Json文件,运行javascript文件?
- 使用child_process。execSync但保持输出在控制台
- SyntaxError:在严格模式下使用const
- 在Node.js中递归复制文件夹
- 如何在node.js中设置默认时区?
- “react-scripts”不被视为内部或外部命令