协慌网

登录 贡献 社区

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

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

答案

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

目前的答案

您可以使用fs.existsSync()

var fs = require('fs');
if (fs.existsSync(path)) {
    // Do something
}

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

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

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


历史答案

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

  • 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) ,但请注意,如果文件 / 目录不存在,那就是错误; docs for fs.stat建议使用fs.access如果你需要检查是否存在而不打开)
  • 2016 年 12 月更新
    fs.exists()仍然被弃用,但fs.existsSync()不再被弃用。所以你现在可以安全地使用它。

2010 年的原始答案:

您可以使用statSynclstatSyncdocs 链接 ),它们为您提供fs.Stats对象 。通常,如果函数的同步版本可用,则它将与最终具有Sync的异步版本具有相同的名称。所以statSyncstat的同步版本; lstatSynclstat等的同步版本。

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

...... 同样如果它是一个文件,那就是isFile ; 如果它是一个块设备,那就是isBlockDevice等等。注意try/catch ; 如果条目根本不存在则抛出错误。

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

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

它不需要try/catch ,但是它不会提供有关它是什么的信息,只是它就在那里。 path.existsSync很久以前就被弃用了。


旁注:您已明确询问如何同步检查,因此我使用了上述函数的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
    }
});

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

2012 年 9 月更新

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

例:

var fs = require('fs');

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

// Or

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

2015 年 2 月更新

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

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

2015 年 12 月更新

不知道它有多久,但也有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
    }
});

2016 年 12 月更新

您可以使用fs.existsSync()

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

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

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

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

更新:

path.existspath.existsSync现已弃用请使用fs.existsfs.existsSync

2016 年更新:

fs.existsfs.existsSync已被弃用 。请改用fs.stat()fs.access()

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

var fs = require('fs');

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

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

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

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

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