sac*_*hin 250 filesystems node.js
在我的Node应用程序中,我需要删除一个包含一些文件的目录,但fs.rmdir只适用于空目录.我怎样才能做到这一点?
Mor*_*len 278
有一个名为rimraf(https://npmjs.org/package/rimraf)的模块.它提供与以下相同的功能rm -Rf
异步使用:
var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });
Run Code Online (Sandbox Code Playgroud)
同步使用:
rimraf.sync("/some/directory");
Run Code Online (Sandbox Code Playgroud)
Sha*_*der 194
同步删除文件夹
const fs = require('fs');
const Path = require('path');
const deleteFolderRecursive = function(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach((file, index) => {
const curPath = Path.join(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)
Pie*_*oui 156
大多数使用fsNode.js 的人都希望函数接近处理文件的"Unix方式".我正在使用fs-extra带来所有很酷的东西:
fs-extra包含未包含在vanilla Node.js fs包中的方法.例如mkdir -p,cp -r和rm -rf.
更好的是,fs-extra是原生fs的替代品.fs中的所有方法都是未修改的并附加到它上面.这意味着你可以用fs-extra替换fs :
// this can be replaced
const fs = require('fs')
// by this
const fs = require('fs-extra')
Run Code Online (Sandbox Code Playgroud)
然后你可以这样删除一个文件夹:
fs.removeSync('/tmp/myFolder');
//or
fs.remove('/tmp/myFolder', callback);
Run Code Online (Sandbox Code Playgroud)
小智 37
使用Node.js 12.10,您最终可以做一个简单的事情:
fs.rmdir(dir, { recursive: true });
Run Code Online (Sandbox Code Playgroud)
该recursive选项以递归方式删除整个内容。
小智 27
为节点s14的(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'));
Run Code Online (Sandbox Code Playgroud)
或者:
const fs = require('fs');
fs.rmSync('/path/to/delete', { recursive: true });
console.log('done');
Run Code Online (Sandbox Code Playgroud)
thy*_*bzi 21
我从@oconnecp修改了答案(/sf/answers/1754887991/)
使用path.join可获得更好的跨平台体验.所以,不要忘记要求它.
var path = require('path');
Run Code Online (Sandbox Code Playgroud)
还将功能重命名为rimraf;)
/**
* Remove directory recursively
* @param {string} dir_path
* @see https://stackoverflow.com/a/42505874/3027390
*/
function rimraf(dir_path) {
if (fs.existsSync(dir_path)) {
fs.readdirSync(dir_path).forEach(function(entry) {
var entry_path = path.join(dir_path, entry);
if (fs.lstatSync(entry_path).isDirectory()) {
rimraf(entry_path);
} else {
fs.unlinkSync(entry_path);
}
});
fs.rmdirSync(dir_path);
}
}
Run Code Online (Sandbox Code Playgroud)
mdm*_*ndo 18
从 Node 文档中可以看到这里。
要获得类似于 Unix 命令的行为
rm -rf,请fs.rm()与 options 一起使用{ recursive: true, force: true }。
例如
import { rm } from 'node:fs/promises';
await rm('/path/to', { recursive: true, force: true });
Run Code Online (Sandbox Code Playgroud)
Suk*_*ima 14
我通常不复活旧线程,但是这里有很多搅动,并且没有rimraf回答,这些对我来说似乎都太复杂了。
首先,在现代Node(> = v8.0.0)中,您可以仅使用节点核心模块来简化流程,完全异步,并以五行功能同时并行化文件的取消链接,同时仍保持可读性:
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);
};
Run Code Online (Sandbox Code Playgroud)
另一方面,对于路径遍历攻击的防护措施不适用于此功能,因为
rm -rf,它接受一个参数,并允许用户进行rm -rf /询问。脚本的责任是保护rm程序本身。.isDirectory()是false对符号链接和取消关联不递归到。最后但并非最不重要的一点是,有一个罕见的竞争条件,即在此递归运行时,如果在正确的时间在此脚本外部取消链接或删除其中一个条目,则递归可能出错。由于这种情况在大多数环境中并不常见,因此很可能会被忽略。但是,如果需要(对于某些极端情况),可以使用以下稍微复杂的示例来缓解此问题:
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);
};
Run Code Online (Sandbox Code Playgroud)
编辑:做isDirectory()一个功能。最后删除实际目录。修复缺少的递归。
Ton*_*rix 11
这是@ SharpCoder的答案的异步版本
const fs = require('fs');
const path = require('path');
function deleteFile(dir, file) {
return new Promise(function (resolve, reject) {
var filePath = path.join(dir, file);
fs.lstat(filePath, function (err, stats) {
if (err) {
return reject(err);
}
if (stats.isDirectory()) {
resolve(deleteDirectory(filePath));
} else {
fs.unlink(filePath, function (err) {
if (err) {
return reject(err);
}
resolve();
});
}
});
});
};
function deleteDirectory(dir) {
return new Promise(function (resolve, reject) {
fs.access(dir, function (err) {
if (err) {
return reject(err);
}
fs.readdir(dir, function (err, files) {
if (err) {
return reject(err);
}
Promise.all(files.map(function (file) {
return deleteFile(dir, file);
})).then(function () {
fs.rmdir(dir, function (err) {
if (err) {
return reject(err);
}
resolve();
});
}).catch(reject);
});
});
});
};
Run Code Online (Sandbox Code Playgroud)
oco*_*ecp 10
我写了这个函数叫做remove folder.它将递归删除某个位置中的所有文件和文件夹.它需要的唯一包是异步.
var async = require('async');
function removeFolder(location, next) {
fs.readdir(location, function (err, files) {
async.each(files, function (file, cb) {
file = location + '/' + file
fs.stat(file, function (err, stat) {
if (err) {
return cb(err);
}
if (stat.isDirectory()) {
removeFolder(file, cb);
} else {
fs.unlink(file, function (err) {
if (err) {
return cb(err);
}
return cb();
})
}
})
}, function (err) {
if (err) return next(err)
fs.rmdir(location, function (err) {
return next(err)
})
})
})
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用节点8+想要asyncronicity并且不希望外部依赖,那么这里是async/await版本:
const path = require('path');
const fs = require('fs');
const util = require('util');
const readdir = util.promisify(fs.readdir);
const lstat = util.promisify(fs.lstat);
const unlink = util.promisify(fs.unlink);
const rmdir = util.promisify(fs.rmdir);
const removeDir = async (dir) => {
try {
const files = await readdir(dir);
await Promise.all(files.map(async (file) => {
try {
const p = path.join(dir, file);
const stat = await lstat(p);
if (stat.isDirectory()) {
await removeDir(p);
} else {
await unlink(p);
console.log(`Removed file ${p}`);
}
} catch (err) {
console.error(err);
}
}))
await rmdir(dir);
console.log(`Removed dir ${dir}`);
} catch (err) {
console.error(err);
}
}
Run Code Online (Sandbox Code Playgroud)
[编辑:使用 node.js v15.5.0]
刚刚尝试使用此处发布的一些解决方案后,我遇到了以下弃用警告:
(node:13202) [DEP0147] 弃用警告:在 Node.js 的未来版本中,如果路径不存在或者是一个文件,fs.rmdir(path, { recursive: true }) 将抛出。使用 fs.rm(path, { recursive: true, force: true }) 代替
fs.rm(path, { recursive: true, force: true });fs.rmSync(path, { recursive: true, force: true });如果你想使用阻塞版本,效果很好。
const fs = require("fs");
fs.rmdir("./test", { recursive: true }, (err) => {
if (err) {
console.error(err);
}
});
Run Code Online (Sandbox Code Playgroud)
提供recursive: true选项。它将递归删除给定路径的所有文件和目录。(假设test根目录存在目录。)
2020年更新
从版本 12.10.0 开始,为选项添加了recursiveOption 。
请注意,递归删除是实验性的。
所以你会做同步:
fs.rmdirSync(dir, {recursive: true});
Run Code Online (Sandbox Code Playgroud)
或者对于异步:
fs.rmdir(dir, {recursive: true});
Run Code Online (Sandbox Code Playgroud)
根据fs文档,fsPromises当前提供了recursive实验性的选项,至少在我自己的 Windows 上的情况下,该选项会删除该目录及其中的任何文件。
fsPromises.rmdir(path, {
recursive: true
})
Run Code Online (Sandbox Code Playgroud)
是否recursive: true删除 Linux 和 MacOS 上的文件?
从 Node.js v14 开始,我们现在可以使用该require("fs").promises.rm函数通过 Promise 删除文件。第一个参数是要删除的文件或文件夹(甚至是不存在的文件或文件夹)。您可以在第二个参数的对象中使用recursive和选项来模仿Shell 命令实用程序force的行为rm-rf。
"use strict";
require("fs").promises.rm("directory", {recursive: true, force: true}).then(() => {
console.log("removed");
}).catch(error => {
console.error(error.message);
});
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢 async/await,则可以使用fs/promisesAPI。
const fs = require('fs/promises');
const removeDir = async (dirPath) => {
await fs.rm(dirPath, {recursive: true});
}
Run Code Online (Sandbox Code Playgroud)
如果您知道文件夹中单个文件的路径并希望删除包含该文件的文件夹。
const fs = require('fs/promises');
const removeDir = async (dirPath) => {
await fs.rm(dirPath, {recursive: true});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
206612 次 |
| 最近记录: |