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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4482686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 13:46:32  来源:igfitidea点击:

Check synchronously if file/directory exists in Node.js

node.jsfs

提问by Ragnis

How can I synchronously check, using node.js, if a file or directory exists?

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

回答by T.J. Crowder

The answer to this question has changed over the years. The currentanswer is here at the top, followed by the various answers over the years in chronological order:

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

Current Answer

当前答案

You can use fs.existsSync():

您可以使用fs.existsSync()

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

It was deprecated for several years, but no longer is. From the docs:

它被弃用了好几年,但现在不再是。从文档:

Note that fs.exists()is deprecated, but fs.existsSync()is not. (The callback parameter to fs.exists()accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync()does not use a callback.)

请注意,fs.exists()已弃用,但fs.existsSync()并非如此。(回调参数fs.exists()接受与其他 Node.js 回调不一致的参数。fs.existsSync()不使用回调。)

You've specifically asked for a synchronouscheck, but if you can use an asynchronouscheck instead (usually best with I/O), use fs.promises.accessif you're using asyncfunctions or fs.access(since existsis deprecated) if not:

您特别要求进行同步检查,但如果您可以使用异步检查(通常最好与 I/O 一起使用),fs.promises.access请在使用async函数时使用,或者fs.access(因为exists已弃用)如果不是:

In an asyncfunction:

在一个async函数中:

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

Or with a callback:

或者使用回调:

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


Historical Answers

历史答案

Here are the historical answers in chronological order:

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

  • Original answer from 2010
    (stat/statSyncor lstat/lstatSync)
  • Update September 2012
    (exists/existsSync)
  • Update February 2015
    (Noting impending deprecation of exists/existsSync, so we're probably back to stat/statSyncor lstat/lstatSync)
  • Update December 2015
    (There's also fs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK), but note that if the file/directory doesn't exist, it's an error; docs for fs.statrecommend using fs.accessif you need to check for existence without opening)
  • Update December 2016
    fs.exists()is still deprecated but fs.existsSync()is no longer deprecated. So you can safely use it now.
  • 2010 年的原始答案
    stat/statSynclstat/ lstatSync
  • 2012 年 9 月更新
    ( exists/ existsSync)
  • 2015 年 2 月更新
    (注意到exists/即将弃用existsSync,所以我们可能会回到stat/statSynclstat/ lstatSync
  • 2015 年 12 月更新
    (还有fs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK),但请注意,如果文件/目录不存在,则为错误;如果您需要在不打开的情况下检查是否存在,fs.stat推荐使用的文档fs.access
  • 2016 年 12 月更新
    fs.exists()仍然被弃用,但fs.existsSync()不再被弃用。所以你现在可以安全地使用它。

Original answer from 2010:

2010年的原始答案:

You can use statSyncor lstatSync(docs link), which give you an fs.Statsobject. In general, if a synchronous version of a function is available, it will have the same name as the async version with Syncat the end. So statSyncis the synchronous version of stat; lstatSyncis the synchronous version of lstat, etc.

您可以使用statSynclstatSync文档链接),它为您提供一个fs.Stats对象。一般来说,如果一个函数的同步版本可用,它将与异步版本具有相同的名称Sync。所以,statSync是的同步版本stat; lstatSync是等的同步版本lstat

lstatSynctells you both whether something exists, and if so, whether it's a file or a directory (or in some file systems, a symbolic link, block device, character device, etc.), e.g. if you need to know if it exists and is a directory:

lstatSync告诉你某个东西是否存在,如果存在,它是一个文件还是一个目录(或在某些文件系统中,一个符号链接、块设备、字符设备等),例如,如果你需要知道它是否存在并且是一个目录:

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) {
    // ...
}

...and similarly, if it's a file, there's isFile; if it's a block device, there's isBlockDevice, etc., etc. Note the try/catch; it throws an error if the entry doesn't exist at all.

...同样,如果它是一个文件,则有isFile; 如果它是块设备,则有isBlockDevice等。请注意try/catch; 如果条目根本不存在,它会引发错误。

If you don't care what the entry isand only want to know whether it exists, you can use path.existsSync(or with latest, fs.existsSync) as noted by user618408:

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

var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}

It doesn't require a try/catchbut gives you no information about what the thing is, just that it's there.path.existsSyncwas deprecated long ago.

它不需要 atry/catch但不提供任何关于事物是什么的信息,只是它在那里。path.existsSync很久以前就被弃用了。



Side note: You've expressly asked how to check synchronously, so I've used the xyzSyncversions of the functions above. But wherever possible, with I/O, it really is best to avoid synchronous calls. Calls into the I/O subsystem take significant time from a CPU's point of view. Note how easy it is to call lstatrather than lstatSync:

旁注:您已明确询问如何同步检查,因此我使用了xyzSync上述函数的版本。但是只要有可能,对于 I/O,最好避免同步调用。从 CPU 的角度来看,调用 I/O 子系统需要花费大量时间。请注意调用lstat而不是调用是多么容易lstatSync

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

But if you need the synchronous version, it's there.

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

Update September 2012

2012 年 9 月更新

The below answer from a couple of years ago is now a bit out of date. The current way is to use fs.existsSyncto do a synchronous check for file/directory existence (or of course fs.existsfor an asynchronous check), rather than the pathversions below.

几年前的以下答案现在有点过时了。当前的方法是使用fs.existsSync同步检查文件/目录是否存在(或者当然 fs.exists是异步检查),而不是path下面的版本。

Example:

例子:

var fs = require('fs');

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

// Or

fs.exists(path, function(exists) {
    if (exists) {
        // Do something
    }
});

Update February 2015

2015 年 2 月更新

And here we are in 2015 and the Node docs now say that fs.existsSync(and fs.exists) "will be deprecated". (Because the Node folks think it's dumb to check whether something exists before opening it, which it is; but that's not the only reason for checking whether something exists!)

现在是 2015 年,Node 文档现在说fs.existsSync(和fs.exists)“将被弃用”。(因为 Node 的人认为在打开某个东西之前检查它是否存在是愚蠢的,确实如此;但这不是检查某些东西是否存在的唯一原因!)

So we're probably back to the various statmethods... Until/unless this changes yet again, of course.

所以我们可能会回到各种stat方法......直到/除非这再次发生变化,当然。

Update December 2015

2015 年 12 月更新

Don't know how long it's been there, but there's also fs.access(path, fs.F_OK, ...)/ fs.accessSync(path, fs.F_OK). And at least as of October 2016, the fs.statdocumentationrecommends using fs.accessto do existence checks ("To check if a file exists without manipulating it afterwards, fs.access()is recommended."). But note that the access not being available is considered an error, so this would probably be best if you're expecting the file to be accessible:

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

var fs = require('fs');

try {
    fs.accessSync(path, fs.F_OK);
    // Do something
} catch (e) {
    // It isn't accessible
}

// Or

fs.access(path, fs.F_OK, function(err) {
    if (!err) {
        // Do something
    } else {
        // It isn't accessible
    }
});

Update December 2016

2016 年 12 月更新

You can use fs.existsSync():

您可以使用fs.existsSync()

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

It was deprecated for several years, but no longer is. From the docs:

它被弃用了好几年,但现在不再是。从文档:

Note that fs.exists()is deprecated, but fs.existsSync()is not. (The callback parameter to fs.exists()accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync()does not use a callback.)

请注意,fs.exists()已弃用,但fs.existsSync()并非如此。(回调参数fs.exists()接受与其他 Node.js 回调不一致的参数。fs.existsSync()不使用回调。)

回答by Jeff

Looking at the source, there's a synchronous version of path.exists- path.existsSync. Looks like it got missed in the docs.

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

Update:

更新:

path.existsand path.existsSyncare now deprecated. Please use fs.existsand fs.existsSync.

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

Update 2016:

2016 年更新:

fs.existsand fs.existsSynchave alsobeen deprecated. Use fs.stat()or fs.access()instead.

fs.exists并且fs.existsSync被弃用了。使用fs.stat()fs.access()代替。

Update 2019:

2019 年更新:

use fs.existsSync. It's not deprecated. https://nodejs.org/api/fs.html#fs_fs_existssync_path

使用fs.existsSync. 它没有被弃用。 https://nodejs.org/api/fs.html#fs_fs_existssync_path

回答by BobDickinson

Using the currently recommended (as of 2015) APIs (per the Node docs), this is what I do:

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

var fs = require('fs');

function fileExists(filePath)
{
    try
    {
        return fs.statSync(filePath).isFile();
    }
    catch (err)
    {
        return false;
    }
}

In response to the EPERM issue raised by @broadband in the comments, that brings up a good point. fileExists() is probably not a good way to think about this in many cases, because fileExists() can't really promise a boolean return. You may be able to determine definitively that the file exists or doesn't exist, but you may also get a permissions error. The permissions error doesn't necessarily imply that the file exists, because you could lack permission to the directory containing the file on which you are checking. And of course there is the chance you could encounter some other error in checking for file existence.

针对@broadband 在评论中提出的 EPERM 问题,这提出了一个很好的观点。在许多情况下,fileExists() 可能不是考虑这一点的好方法,因为 fileExists() 不能真正承诺布尔返回。您可能能够明确地确定该文件是否存在,但您也可能会收到权限错误。权限错误并不一定意味着该文件存在,因为您可能缺乏对包含您正在检查的文件的目录的权限。当然,您可能会在检查文件存在时遇到其他一些错误。

So my code above is really doesFileExistAndDoIHaveAccessToIt(), but your question might be doesFileNotExistAndCouldICreateIt(), which would be completely different logic (that would need to account for an EPERM error, among other things).

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

While the fs.existsSync answer addresses the question asked here directly, that is often not going to be what you want (you don't just want to know if "something" exists at a path, you probably care about whether the "thing" that exists is a file or a directory).

虽然 fs.existsSync 答案直接解决了此处提出的问题,但这通常不是您想要的(您不仅想知道路径中是否存在“某物”,您可能还关心“某物”是否存在)存在的是文件或目录)。

The bottom line is that if you're checking to see if a file exists, you are probably doing that because you intend to take some action based on the result, and that logic (the check and/or subsequent action) should accommodate the idea that a thing found at that path may be a file or a directory, and that you may encounter EPERM or other errors in the process of checking.

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

回答by Melbourne2991

Another Update

另一个更新

Needing an answer to this question myself I looked up the node docs, seems you should notbe using fs.exists, instead use fs.open and use outputted error to detect if a file does not exist:

我自己需要回答这个问题,我查了节点文档,似乎你应该使用 fs.exists,而是使用 fs.open 并使用输出的错误来检测文件是否不存在:

from the docs:

从文档:

fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.

In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.

fs.exists() 是一个时代错误,仅因历史原因而存在。几乎永远不会有理由在您自己的代码中使用它。

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

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

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

回答by broadband

I use below function to test if file exists. It catches also other exceptions. So in case there are rights issues e.g. chmod ugo-rwx filenameor in Windows Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..function returns exception as it should. The file exists but we don't have rights to access it. It would be wrong to ignore this kinds of exceptions.

我使用下面的函数来测试文件是否存在。它还捕获其他异常。因此,如果存在权利问题,例如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, ...
  }
}

Exception output, nodejs errors documentationin case file doesn't exist:

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

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

Exception in case we don't have rights to the file, but exists:

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

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

回答by gsalgadotoledo

fs.exists() is deprecated dont use it https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

fs.exists() 已弃用,请勿使用 https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

You could implement the core nodejs way used at this: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86

您可以实现在此使用的核心 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;
}

this will return the stats object then once you've got the stats object you could try

这将返回 stats 对象,然后一旦您获得了 stats 对象,您就可以尝试

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

回答by jstice4all

Some answers here says that fs.existsand fs.existsSyncare both deprecated. According to the docs this is no more true. Only fs.existsis deprected now:

这里的一些答案说,fs.exists并且fs.existsSync都已弃用。根据文档,这不再是真的。fs.exists现在只弃用:

Note that fs.exists() is deprecated, but fs.existsSync() is not. (The callback parameter to fs.exists() accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync() does not use a callback.)

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

So you can safely use fs.existsSync()to synchronously check if a file exists.

所以你可以安全地使用fs.existsSync()来同步检查文件是否存在。

回答by Ivo Wetzel

The pathmodule does not provide a synchronous version of path.existsso you have to trick around with the fsmodule.

path模块不提供同步版本,path.exists因此您必须使用该fs模块。

Fastest thing I can imagine is using fs.realpathSyncwhich will throw an error that you have to catch, so you need to make your own wrapper function with a try/catch.

我能想象到的最快的事情是使用fs.realpathSync它会抛出一个你必须捕获的错误,所以你需要使用 try/catch 制作自己的包装函数。

回答by Ivo Wetzel

Using fileSystem (fs) tests will trigger error objects, which you then would need to wrap in a try/catch statement. Save yourself some effort, and use a feature introduce in the 0.4.x branch.

使用文件系统 (fs) 测试将触发错误对象,然后您需要将其包装在 try/catch 语句中。节省一些精力,并使用 0.4.x 分支中引入的功能。

var path = require('path');

var dirs = ['one', 'two', 'three'];

dirs.map(function(dir) {
  path.exists(dir, function(exists) {
    var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
    console.log(message);
  });
});

回答by Grallen

The documents on fs.stat()says to use fs.access()if you are not going to manipulate the file. It did not give a justification, might be faster or less memeory use?

如果您不打算操作该文件,则文件上fs.stat()说要使用fs.access()。它没有给出理由,可能是更快还是更少的内存使用?

I use node for linear automation, so I thought I share the function I use to test for file existence.

我使用 node 进行线性自动化,所以我想我分享了我用来测试文件存在的函数。

var fs = require("fs");

function exists(path){
    //Remember file access time will slow your program.
    try{
        fs.accessSync(path);
    } catch (err){
        return false;
    }
    return true;
}