错误:" EPERM:不允许操作"而删除目录不是emty

时间:2018-02-28 08:41:48

标签: javascript node.js


我试图删除Nodejs文件系统中非空的文件夹。删除了根文件夹中的所有文件夹,但未删除根文件夹。我用空文件夹再试一次,它成功了!

const rmDir =  (dirPath) => {
  try { var files = fs.readdirSync(dirPath); }
  catch(e) { return; }
  if (files.length > 0)
    for (var i = 0; i < files.length; i++) {
      var filePath = dirPath + '/' + files[i];
      if (fs.statSync(filePath).isFile())
        fs.unlinkSync(filePath);
      else
        rmDir(filePath);
    }
  fs.rmdirSync(dirPath);
  return true;
}


这是错误:

(node:16108) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOTEMPTY: directory not empty, rmdir '{dir}'
(node:16108) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

2 个答案:

答案 0 :(得分:1)

你可以递归地工作。像这样:

var fs = require('fs');
var deleteFolderRecursive = function(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).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);
  }
};

或者你可以试试this package (rimraf)

fs 使用shell命令。要删除文件夹 fs ,请使用 rm 而不使用 -rf ,这样您就无法强行使用。希望它有所帮助。

答案 1 :(得分:0)

序言

此答案是对已接受答案的补充。 EPERM(请参阅comments)错误代码也可能是由于路径下的文件仍在取消链接而仍在使用中。在使用Mocha进行单元测试后,设置清理过程时遇到了这个问题。

问题

使用unlink()unlinkSync()取消链接文件可能无法在Windows上按预期方式工作,因为实际上并没有删除文件,而是基本上将其标记为一旦所有文件都删除了释放句柄(请参阅相关的question)。

因此,例如,尽管unlinkSync()成功“删除”了文件,但是当rmdirSync()到达包含文件夹时,它可能因ENOTEMPTY而失败,因为从文件系统的角度来看,该文件仍然存在。

除了轮询文件是否可用之外,如果不受控制的进程正在使用该文件,则您无能为力(请参阅this question),但是如果您只需要进行清理-生成一个子进程,然后退出该进程:

//parent process
const { spawn } = require('child_process');

/**
 * @summary Spawns completely detached child
 * @param {NodeJS.Process} parent 
 * @param {string} path 
 * @param {object} env 
 * @return {NodeJS.Process}
 */
const spawnResponsible = (parent, path, env) => {
    const child = spawn(parent.argv0, [path], {
        env,
        detached: true,
        stdio: "ignore"
    });

    child.unref();

    return child;
};

process.once('beforeExit', () => {
  spawnResponsible(
    process,
    'path to your child process script file',
    { PATHS: [] } //array of paths
  );
});

您的子进程可能看起来像这样(请注意,不建议使用同步方法,除非您进行设置或清理,否则,除非[使用子进程部分解决了问题,但要以运行其他进程为代价],否则无法继续进行) :

//child process

const fs = require('fs');
const pt = require('path');

const { PATHS } = process.env;

/**
 * @summary Cleans root path and subpaths
 * @param {string} rootPath 
 */
const cleanOfEntries = (rootPath) => {
    if (fs.existsSync(rootPath)) {

        const entries = fs.readdirSync(rootPath, { withFileTypes: true });

        for (const entry of entries) {
            const thisPath = pt.resolve(rootPath, entry.name);

            if (fs.existsSync(thisPath)) {
                entry.isDirectory() && cleanOfEntries(thisPath);
                entry.isFile() && fs.unlinkSync(thisPath);
            }
        }

        fs.rmdirSync(rootPath);
    }
};

for (const path of PATHS.split(',')) {
    cleanOfEntries(path);
}

参考

  1. unlinkSync() docs
  2. spawn() docs
  3. rmdirSync() docs