一个关于Nodejs删除本地文件夹报错的问题
一个关于Nodejs删除本地文件夹报错的问题
情况是酱紫的:
比如我本地有一套文件目录:./build/test/css/i
此时我的文件资源管理器处于此套目录内的某一级目录
var fs = require('fs');
var f = require('./file');
f.del('./build');
这时在build文件夹中执行以上代码,会抛出如下异常:
fs.js:623
return binding.rmdir(pathModule._makeLong(path));
^
Error: ENOTEMPTY, directory not empty 'D:\Test\build\Test\css'
at Object.fs.rmdirSync (fs.js:623:18)
at Object.module.exports.del (D:\Test\file.js:99:10)
at D:\Test\file.js:93:22
at Array.forEach (native)
at Object.module.exports.del (D:\Test\file.js:91:11)
at D:\Test\file.js:93:22
at Array.forEach (native)
at Object.module.exports.del (D:\Test\file.js:91:11)
at Object.<anonymous> (D:\Test\change.js:4:3)
at Module._compile (module.js:456:26)
从错误异常来看,是因为某级目录不是空目录,所以无法删除。但是,我的f.del()
方法已经是递归删除了,只是在文件资源管理器处于其中的某一级目录时,才会删除不成功。
个人分析是因为当前要删除的文件夹被资源管理器占用着,所以会有某种权限上的问题。可是怎么解决呢,已经google多日也木有找到靠谱的解决方案,希望各位路过的大神儿能给看看,在此先行作辑了!!!
下面是f.del()
的源码:
del:function(source,callback){
var removedAll = true;
var source = f.realpath(source);
if(source){
if(f.isDir(source)){
var files;
try {
files = fs.readdirSync(source);
} catch (err) {
console.log(err);
}
files.forEach(function(name){
if(name != '.' && name != '..') {
removedAll = f.del(source + '/' + name) && removedAll;
}
});
if(removedAll) {
if(fs.existsSync(source)){
fs.rmdirSync(source);
}
if(callback) callback();
}
} else if(f.isFile(source)){
if (f.isWin && f.exists(source)) {
fs.chmodSync(source, 666);
}
fs.unlinkSync(source);
} else {
removedAll = false;
}
} else {
//
}
return removedAll;
}
针对这个问题,我们可以从几个方面入手解决。首先,我们需要确保在删除文件夹之前,文件夹没有被其他进程占用。其次,我们需要确保我们有足够的权限来删除文件夹。最后,我们需要检查我们的递归删除逻辑是否正确。
解决方案
1. 确保文件夹未被占用
当文件资源管理器打开某个文件夹时,该文件夹可能被占用,导致无法删除。可以尝试关闭文件资源管理器后再执行删除操作。
2. 检查权限
确保当前用户有足够的权限来删除文件夹及其内容。可以通过提升程序运行的权限或修改文件夹的权限来解决。
3. 优化递归删除逻辑
我们可以使用 fs.promises
和 async/await
来更优雅地处理递归删除操作,并捕获所有可能的错误。
示例代码
const fs = require('fs').promises;
const path = require('path');
async function delRecursive(dirPath) {
try {
const items = await fs.readdir(dirPath);
for (let item of items) {
const fullPath = path.join(dirPath, item);
const stats = await fs.stat(fullPath);
if (stats.isDirectory()) {
await delRecursive(fullPath);
} else {
await fs.unlink(fullPath);
}
}
await fs.rmdir(dirPath);
console.log(`Successfully deleted ${dirPath}`);
} catch (error) {
console.error(`Error deleting ${dirPath}:`, error.message);
}
}
// 使用示例
(async () => {
await delRecursive('./build');
})();
解释
- 异步函数:使用
fs.promises
和async/await
可以避免回调地狱,并且更容易处理错误。 - 读取目录:通过
fs.readdir
读取目录中的所有文件和子目录。 - 递归删除:对于每个文件,如果是目录,则递归调用
delRecursive
;如果是文件,则直接删除。 - 删除目录:最后删除空目录。
- 错误处理:使用
try/catch
块捕获并处理可能的错误。
通过这种方式,我们可以更可靠地删除包含子目录和文件的文件夹。
我也遇到了,递归删除不成功,明明是空的,但就是显示说文件夹不是空
根据你的描述,问题可能在于文件资源管理器占用了 build
文件夹,导致无法删除。你可以尝试使用 rimraf
这样的库来递归删除文件夹,它能够更好地处理这种场景。
示例代码
const rimraf = require("rimraf");
rimraf("./build", (err) => {
if (err) {
console.error("删除失败:", err);
} else {
console.log("删除成功");
}
});
解释
-
引入
rimraf
库:rimraf
是一个跨平台的库,可以用来删除文件夹及其内容。
-
调用
rimraf
方法:rimraf("./build", callback)
方法用于删除./build
文件夹。- 回调函数会在操作完成后执行,如果出现错误则会打印错误信息。
注意事项
- 确保在删除文件夹之前关闭所有占用该文件夹的应用程序或文件资源管理器,以避免权限问题。
- 使用
rimraf
可以减少自己编写递归删除逻辑的工作量,并且更加健壮。
这样应该可以解决你的问题。如果还有其他问题,请随时告知。