我已经阅读了Node.js的文档,除非我错过了一些东西,否则它不会告诉某些操作中的参数包含什么,特别是fs.mkdir()。正如您在文档中看到的,它不是很多。

目前,我有这段代码,它试图创建一个文件夹或使用一个现有的:

fs.mkdir(path,function(e){
    if(!e || (e && e.code === 'EEXIST')){
        //do something with contents
    } else {
        //debug
        console.log(e);
    }
});

但我想知道这是正确的方法吗?检查代码EEXIST是知道文件夹已经存在的正确方法吗?我知道我可以在创建目录之前执行fs.stat(),但这已经是两次对文件系统的访问了。

其次,是否有一个完整的或至少更详细的Node.js文档,其中包含错误对象包含什么,参数表示什么等细节。


当前回答

我提出了一个没有模块的解决方案(对于可维护性,不建议积累模块,特别是对于可以用几行代码编写的小函数……):

最近更新:

在v10.12.0中,NodeJS实现了递归选项:

// Create recursive folder
fs.mkdir('my/new/folder/create', { recursive: true }, (err) => { if (err) throw err; });

更新:

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create 
function mkdirpath(dirPath)
{
    if(!fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK))
    {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');

其他回答

fs的node.js文档。mkdir基本上遵循Linux手册页的mkdir(2)。这表明,如果路径存在,但不是目录,也将指示EEXIST,如果你走这条路,就会创建一个尴尬的角落情况。

你最好调用fs。Stat将告诉您路径是否存在,以及它是否是单个调用中的目录。对于(我假设的是)目录已经存在的正常情况,它只是一次文件系统命中。

这些fs模块方法是对原生C api的精简包装,所以你必须检查node.js文档中引用的手册页以获得详细信息。

上面@Liberateur的答案对我来说无效(Node v8.10.0)。 做了一点修改,但我不确定这是否是一个正确的方式。请建议。

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create
function mkdirpath(dirPath)
{
    try {
        fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
    }
    catch(err) {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');

在我看来,在使用Javascript编写代码时,最好不要计算文件系统的命中次数。 然而,(1)stat & mkdir和(2)mkdir和检查(或丢弃)错误代码,这两种方法都是正确的方法来做你想要的。

编辑:因为这个答案很流行,我更新了它,以反映最新的实践。

节点> = 10

Node的fs的新{recursive: true}选项现在允许本机执行此操作。该选项模仿UNIX的mkdir -p的行为。它将递归地确保路径的每个部分都存在,如果其中任何一部分存在,也不会抛出错误。

(注意:它仍然可能抛出诸如EPERM或EACCESS之类的错误,所以如果你的实现容易受到它的影响,最好还是将它包装在try {} catch (e){}中。)

同步版本。

fs.mkdirSync(dirpath, { recursive: true })

异步版本

await fs.promises.mkdir(dirpath, { recursive: true })

Node旧版本

使用try {} catch (err){},您可以非常优雅地实现这一点,而不会遇到竞争条件。

为了避免在检查是否存在和创建目录之间出现死时间,我们简单地尝试直接创建它,如果它是EEXIST(目录已经存在),则忽略错误。

但是,如果错误不是EEXIST,我们应该抛出一个错误,因为我们可能在处理EPERM或EACCES之类的错误

function ensureDirSync (dirpath) {
  try {
    return fs.mkdirSync(dirpath)
  } catch (err) {
    if (err.code !== 'EEXIST') throw err
  }
}

对于类似mkdir -p的递归行为,例如./a/b/c,你必须在dirpath的每个部分调用它,例如./a, ./a/b, .a/b/c

如果你想要一个快速而脏的眼线笔,使用这个:

fs.existsSync("directory") || fs.mkdirSync("directory");