如何使用node.js同步检查文件或目录是否存在?


当前回答

const fs = require('fs');

检查以下功能,

if(fs.existsSync(<path_that_need_to_be_checked>)){
  // enter the code to excecute after the folder is there.
}
else{
  // Below code to create the folder, if its not there
  fs.mkdir('<folder_name>', cb function);
}

其他回答

从答案来看,似乎没有官方的API支持(如直接和明确的检查)。许多答案都说要使用stat,但并不严格。例如,我们不能假设stat抛出的任何错误都意味着某些东西不存在。

让我们试着用一些不存在的东西:

$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }

让我们尝试一下现有但我们无法访问的内容:

$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }

至少你会想要:

let dir_exists = async path => {
    let stat;
    try {
       stat = await (new Promise(
           (resolve, reject) => require('fs').stat(path,
               (err, result) => err ? reject(err) : resolve(result))
       ));
    }
    catch(e) {
        if(e.code === 'ENOENT') return false;
        throw e;
    }

    if(!stat.isDirectory())
        throw new Error('Not a directory.');

    return true;
};

问题还不清楚,是你真的希望它是同步的,还是你只希望它写得像是同步的。此示例使用await/async,因此它只以同步方式编写,但以异步方式运行。

这意味着你必须在顶层这样称呼它:

(async () => {
    try {
        console.log(await dir_exists('god'));
        console.log(await dir_exists('fsm/appendage'));
    }
    catch(e) {
        console.log(e);
    }
})();

另一种方法是在异步调用返回的promise上使用.then和.catch。

如果你想检查某个东西是否存在,那么最好确保它是正确类型的东西,比如目录或文件。这包括在示例中。如果不允许使用符号链接,则必须使用lstat而不是stat,因为stat将自动遍历链接。

您可以替换此处的所有异步到同步代码,改用statSync。然而,一旦异步和等待成为普遍支持,Sync调用将变得多余,最终将被贬值(否则,您将不得不在所有地方和链上定义它们,就像异步一样,使其变得毫无意义)。

我使用下面的函数来测试文件是否存在。它还捕捉到其他例外。因此,如果存在权限问题,例如chmod ugo rwx文件名或在Windows中右键单击->财产->安全->高级->权限条目:空列表。。函数应返回异常。该文件存在,但我们无权访问它。忽略此类异常是错误的。

function fileExists(path) {

  try  {
    return fs.statSync(path).isFile();
  }
  catch (e) {

    if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
      console.log("File does not exist.");
      return false;
    }

    console.log("Exception fs.statSync (" + path + "): " + e);
    throw e; // something else went wrong, we don't have rights, ...
  }
}

异常输出,nodejs错误文档,以防文件不存在:

{
  [Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'X:\\delsdfsdf.txt'
}

如果我们没有该文件的权限,但存在,则出现异常:

{
  [Error: EPERM: operation not permitted, stat 'X:\file.txt']
  errno: -4048,
  code: 'EPERM',
  syscall: 'stat',
  path: 'X:\\file.txt'
}

这里有一个简单的包装解决方案:

var fs = require('fs')
function getFileRealPath(s){
    try {return fs.realpathSync(s);} catch(e){return false;}
}

用法:

适用于目录和文件如果项存在,则返回文件或目录的路径如果项不存在,则返回false

例子:

var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
    console.log('file/dir not found: '+pathToCheck);
} else {
    console.log('file/dir exists: '+realPath);
}

确保使用==运算符测试return是否等于false。在适当的工作条件下,fs.realpathSync()返回false是没有逻辑原因的,所以我认为这应该可以100%工作。

我更希望看到一个不会产生错误和性能影响的解决方案。从API的角度来看,fs.exists()似乎是最优雅的解决方案。

您可以使用fs extra(npm i fs extra)及其fs.ensureFile或用于目录fs.ensure Dir,因为fs.exists已被取消处理,fs.access不建议您在使用该文件后对其进行编辑“在调用fs.open()、fs.readFile()或fs.writeFile()之前,不要使用fs.access()检查文件的可访问性。这样做会引入竞争条件,因为其他进程可能会在两次调用之间更改文件的状态。相反,用户代码应该直接打开/读取/写入文件,并在文件不可访问时处理引发的错误。"

很可能,如果你想知道文件是否存在,你计划在它存在的时候需要它。

function getFile(path){
    try{
        return require(path);
    }catch(e){
        return false;
    }
}