同步检查Node.js中是否存在文件/目录

Rag*_*nis 1113 node.js

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

T.J*_*der 2111

多年来,这个问题的答案发生了变化.在目前的答案是在此间举行的顶部,然后用按时间顺序多年的各种答案:

目前的答案

你可以使用fs.existsSync():

const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
    // Do something
}
Run Code Online (Sandbox Code Playgroud)

它被弃用了几年,但不再是.来自文档:

请注意,fs.exists()不推荐使用,但fs.existsSync()不是.(用于fs.exists()接受与其他Node.js回调不一致的参数的回调参数.fs.existsSync()不使用回调.)

您已经特别要求进行同步检查,但是如果您可以使用异步检查(通常最好使用I/O),请使用fs.promises.access(因为async不推荐使用).


历史答案

以下是按时间顺序排列的历史答案:

  • 2010年的原始答案
    (fs.access/ existsasync/ stat)
  • 2012年9月更新
    (statSync/ lstat)
  • 2015年2月更新
    (注意即将弃用lstatSync/ exists,因此我们可能会回到existsSync/ existsexistsSync/ stat)
  • 2015年12月更新
    (还有statSync/ lstat,但请注意,如果文件/目录不存在,则表示错误; 如果您需要检查存在而不打开,lstatSync建议使用文档fs.access(path, fs.F_OK, function(){}))
  • 2016年12月更新
    fs.accessSync(path, fs.F_OK)仍然已弃用,但fs.stat不再弃用.所以你现在可以安全地使用它.

2010年的原始答案:

您可以使用fs.accessfs.exists()(文档链接),它为您提供一个fs.existsSync()对象.通常,如果函数的同步版本可用,则它将与statSync最终的异步版本具有相同的名称.所以,lstatSync是的同步版本fs.Stats; Sync是等的同步版本statSync等.

stat 告诉你两者是否存在,如果存在,是否是文件或目录(或在某些文件系统,符号链接,块设备,字符设备等),例如,如果你需要知道它是否存在,是目录:

try {
    await fs.promises.access("somefile");
    // The check succeeded
} catch (error) {
    // The check failed
}
Run Code Online (Sandbox Code Playgroud)

......同样如果它是一个文件,那就是lstatSync; 如果它是一个块设备,那么lstat等等等.注意lstatSync; 如果条目根本不存在则抛出错误.

如果您不关心条目什么,只想知道它是否存在,您可以使用isFile(或最新的isBlockDevice),如user618408所述:

fs.access("somefile", error => {
    if (!error) {
        // The check succeeded
    } else {
        // The check failed
    }
});
Run Code Online (Sandbox Code Playgroud)

它不需要a try/catch,但是没有给出关于这是什么的信息,只是它就在那里. path.existsSync很久以前就被弃用了.


旁注:您已明确询问如何同步检查,因此我使用了fs.existsSync上述功能的版本.但只要有可能,使用I/O,最好避免同步调用.从CPU的角度来看,调用I/O子系统需要很长时间.注意调用是否容易,try/catch而不是path.existsSync:

var fs = require('fs');
try {
    // Query the entry
    stats = fs.lstatSync('/the/path');

    // Is it a directory?
    if (stats.isDirectory()) {
        // Yes it is
    }
}
catch (e) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是如果你需要同步版本,它就在那里.

2012年9月更新

几年前的答案现在有点过时了.当前的方法是xyzSync用于对文件/目录存在进行同步检查(当然还有 lstat异步检查),而不是lstatSync下面的版本.

例:

var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}
Run Code Online (Sandbox Code Playgroud)

2015年2月更新

在这里,我们在2015年,Node文档现在说fs.existsSync(和fs.exists)"将被弃用".(因为节点的人认为在打开它之前检查是否存在某些东西是愚蠢的,它是什么;但这不是检查某些东西是否存在的唯一原因!)

所以我们可能会回到各种path方法......当然,除非这种情况再次发生变化.

2015年12月更新

不知道它有多久,但也有fs.existsSync/fs.exists.至少截至2016年10月,stat文档建议使用fs.access(path, fs.F_OK, ...)进行存在检查("fs.accessSync(path, fs.F_OK)建议检查文件是否存在而不进行操作,").但请注意,访问不可用被视为错误,因此如果您希望可以访问该文件,这可能是最好的:

// Is it a directory?
lstat('/the/path', function(err, stats) {
    if (!err && stats.isDirectory()) {
        // Yes it is
    }
});
Run Code Online (Sandbox Code Playgroud)

2016年12月更新

你可以使用fs.stat:

var fs = require('fs');

if (fs.existsSync(path)) {
    // Do something
}

// Or

fs.exists(path, function(exists) {
    if (exists) {
        // Do something
    }
});
Run Code Online (Sandbox Code Playgroud)

它被弃用了几年,但不再是.来自文档:

请注意,fs.access不推荐使用,但fs.access()不是.(用于fs.existsSync()接受与其他Node.js回调不一致的参数的回调参数.fs.exists()不使用回调.)

  • 如果文件不存在,则statSync会触发错误. (31认同)
  • @PetrHurtak:它不是*总是*(因为有很多原因可以检查存在),但是如果要打开*文件,最好只发出`open`调用并处理异常或者无论如何找不到文件.毕竟,现实世界是混乱的:如果你先检查它就在那里,那并不意味着当你试图打开它时它仍然存在; 如果你先检查它并不存在,那并不意味着它不会在那之后.这样的时间似乎是边缘情况,但它们始终**.所以**如果**你要打开,没有必要先检查. (29认同)
  • "节点人们认为在打开它之前检查某些东西是否存在是愚蠢的,这就是它;" 为什么检查文件是否存在是否愚蠢? (13认同)
  • 在这里,我认为这是一个反模式,以用于控制流量的错误:[链接](http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious -antipattern,如果那么为什么) (12认同)
  • path.exists和path.existsSync都被弃用,转而使用fs.exists和fs.existsSync (6认同)
  • @jeromeyers:你可以,但Ionică[已经为你做过](https://github.com/IonicaBizau/node-is-there)(参见[评论上面](http://stackoverflow.com/questions/ 4482686 /签同步-IF-文件目录存在-在节点-JS/4482701?noredirect = 1个#comment45808351_4482701)).:-) (4认同)
  • 大声笑.我像几年一样检查这个帖子,每次都有新的东西))) (4认同)
  • 在我看来,使用错误控制流是一种反模式,它会导致更多的代码.所以他们正在弃用一个函数,其他人必须在自己的库中重新实现?WTF ...... (3认同)
  • Upvote保持答案更新,精湛.希望更多的人这样做. (3认同)
  • 我不记得曾经看到过一些不被弃用的东西。 (3认同)
  • @Jesse:`exists`没有告诉你它是一个目录,它可能是一个文件或管道或其他文件系统对象.当然不是"严重"过于复杂?`existsSync`只会替换`lstatSync`调用,其余的只是为了展示它在循环中的工作方式.(不知道为什么我认为这是必要的.) (2认同)
  • `fs.exists`和`fs.existsSync`将被弃用.我创建了[`is-there`库来替换它们](https://github.com/IonicaBizau/node-is-there).@TJCrowder如果你愿意,你可以把它包括在你的答案中. (2认同)
  • 我不赞成这一点的唯一原因是柜台:1337 (2认同)

小智 119

查看源代码,有一个同步版本path.exists- path.existsSync.看起来它在文档中被遗漏了.

更新:

path.existspath.existsSync现在不推荐使用.请使用fs.existsfs.existsSync.

2016年更新:

fs.exists并且fs.existsSync被弃用了.请改用fs.stat()fs.access().

  • 实际上,最近的答案是:不推荐使用path.existsSync.它现在称为`fs.existsSync`. (21认同)
  • 现在文档说fs.exists将被弃用.http://nodejs.org/api/fs.html#fs_fs_existssync_path (9认同)
  • currenct docs(版本~9)只将`fs.exists`标记为已弃用,而`fs.existsSync`则不是! (6认同)

Bob*_*son 54

使用当前推荐的(截至2015年)API(根据Node文档),这就是我所做的:

var fs = require('fs');

function fileExists(filePath)
{
    try
    {
        return fs.statSync(filePath).isFile();
    }
    catch (err)
    {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

针对@broadband在评论中提出的EPERM问题,这提出了一个很好的观点.在许多情况下,fileExists()可能不是一个考虑这个问题的好方法,因为fileExists()实际上不能保证布尔返回.您可能确定该文件存在或不存在,但您可能还会收到权限错误.权限错误并不一定意味着文件存在,因为您可能缺少包含要检查的文件的目录的权限.当然,在检查文件存在时,您可能会遇到其他错误.

所以我上面的代码实际上是doFileExistAndDoIHaveAccessToIt(),但你的问题可能是doFileNotExistAndCouldICreateIt(),这将是完全不同的逻辑(需要考虑EPERM错误等).

虽然fs.existsSync回答直接解决了这里提出的问题,但通常不会是你想要的(你不只是想知道路径上是否存在"某事"),你可能会关心"事物"是否存在存在的是文件或目录).

最重要的是,如果您正在检查文件是否存在,那么您可能正在这样做,因为您打算根据结果采取某些操作,并且该逻辑(检查和/或后续操作)应该适应这个想法在该路径中找到的东西可能是文件或目录,并且您在检查过程中可能会遇到EPERM或其他错误.

  • 很好,我加了|| isDirectory()使其成为文件/文件夹检查程序.var stats = fs.statSync(filePath);返回stats.isFile()|| stats.isDirectory(); (4认同)
  • 如果程序没有访问该文件的权限,即使文件存在,它仍会返回false,即从文件chmod ugo-rwx file.txt或Windows右键单击中删除所有装备...异常消息:异常fs.statSync(./ f.txt):错误:EPERM:不允许操作,stat'X:\ f.txt'.所以这个案例不在上层代码中. (3认同)
  • 哇,JS有时会智障。可以肯定的是,您有97%的时间会使用该文件,但3%的用户没有简单的`file.exists()`实用程序,而是迫使我们将其包装在try catch中吗?变得真实...今日的itch子。 (2认同)

Mel*_*991 20

另一个更新

需要回答这个问题,我自己,我抬起头节点文档,看来你应该使用fs.exists来,改用fs.open和使用输出错误,如果一个文件不存在检测:

来自文档:

fs.exists()是一种时代错误,只是出于历史原因而存在.几乎没有理由在你自己的代码中使用它.

特别是,在打开文件之前检查文件是否存在是一种反模式,使您容易受到竞争条件的影响:另一个进程可能会在调用fs.exists()和fs.open()之间删除该文件.只需打开文件并在错误处理时处理错误.

http://nodejs.org/api/fs.html#fs_fs_exists_path_callback

  • 这个弃用让我感到困惑.打开一个文件只是为了查看是否抛出错误,当需要知道文件的存在时,这似乎是浪费资源. (6认同)
  • 对于那些仍然需要“存在”和“存在同步”的对象,我创建了[`is-there`](https://github.com/IonicaBizau/node-is-there)。 (2认同)

小智 13

const fs = require('fs');
Run Code Online (Sandbox Code Playgroud)

检查如下函数,

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);
}
Run Code Online (Sandbox Code Playgroud)


bro*_*and 11

我使用下面的函数来测试文件是否存在.它还捕获了其他例外情况.因此,如果存在权限问题,例如chmod ugo-rwx filename或在Windows Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..函数中返回异常应该如此.该文件存在,但我们无权访问它.忽略这种例外是错误的.

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, ...
  }
}
Run Code Online (Sandbox Code Playgroud)

案例文件中不存在异常输出,nodejs错误文档:

{
  [Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'X:\\delsdfsdf.txt'
}
Run Code Online (Sandbox Code Playgroud)

如果我们没有文件权限但存在,则例外:

{
  [Error: EPERM: operation not permitted, stat 'X:\file.txt']
  errno: -4048,
  code: 'EPERM',
  syscall: 'stat',
  path: 'X:\\file.txt'
}
Run Code Online (Sandbox Code Playgroud)

  • 确实如此,这是最新的答案之一,因为节点已弃用了最后的37种方法 (2认同)

gsa*_*edo 5

不建议使用fs.exists(),不要使用它 https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

您可以实现此处使用的核心nodejs方式:https : //github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86

function statPath(path) {
  try {
    return fs.statSync(path);
  } catch (ex) {}
  return false;
}
Run Code Online (Sandbox Code Playgroud)

这将返回stats对象,然后一旦获得s​​tats对象,您可以尝试

var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
  // do something
}
Run Code Online (Sandbox Code Playgroud)