scp 目录不存在_在不使用fs.exists的情况下检查文件/目录是否存在?(译)

任何花了时间编写Node的人都有可能使用了文件系统模块。此核心模块中有一个方法与其他所有方法都不同,据大多数专家说,尽管它在许多其他开发人员中很受欢迎,但根本没有人使用。因此该方法已被弃用多年。当然,我谈论的是fs.exists(和fs.existsSync)。


对于一些人来说,这是一个非常有争议的问题--比如看这个问题或这一个。弃用它的原因是,与所有其他文件系统方法不同,它不使用规范的nodeback API。此外,它的主要用例场景(在打开之前检查文件是否存在)实际上是一种反模式,应通过尝试打开该文件并可能处理该错误来替代它。

但是,尽管它已经存在了很长时间,但仍然有大量的人继续使用fs.exists,并且某些新手或相对新手肯定对应该使用什么感到困惑。至少我自己第一次使用时也遇到这个问题。

尽管我同意该方法通常是多余的,有时甚至是完全没有意义的(在可能发生一些特殊情况并且可能在此期间将其删除的情况下,在对该文件执行某些操作之前检查文件是否有帮助),但我确信许多人会合理使用此方法,如果它被设计的足够好。

因此,如果您正在寻找fs.exists(Sync)的替代品,请继续阅读下面的内容,这是关于如何在不使用(这个不建议使用的方法)的情况下检查文件或目录是否存在的简短讨论。

Synchronous exists

建议同步操作文件系统绝非我本人,但是它更简单了,所以让我们先从这里简单的内容开始。

官方fs文档建议改为使用fs.statSyncfs.accessSync,因此让我们一起来研究一下。

fs.accessSync

此方法检查文件的可访问性,而仅检查其可访问性。如果无法访问该文件,它将引发错误;如果可以访问,它将完全不执行任何操作。

因此,假设您要在尝试创建myDir目录之前检查是否存在,/path/to/myDir表示其目录:

try {
  fs.accessSync(myDir);
} catch (e) {
  fs.mkdirSync(myDir);
}

或者,如果您更喜欢重新创建,用来代替fs.existsSync

function fsExistsSync(myDir) {
  try {
    fs.accessSync(myDir);
    return true;
  } catch (e) {
    return false;
  }
}
if (!fsExists(myDir)) {
  fs.mkdirSync(myDir);
}

fs.statSync

上面的代码有一个问题:如果myDir存在,但不是目录而是恰好具有相同名称的文件,该怎么办?在这种情况下,该路径将是可访问的,但它不是文件夹,并且您可能最终会在讨厌的调试中大吼大叫,之后的其他原因也因此而导致失败。

解决方案是使用fs.statSyncisDirectoryisFile方法返回的变量stats。这是一个同步函数,用于检查给定路径是否存在以及是否为目录:

function isDirSync(aPath) {
  try {
    return fs.statSync(aPath).isDirectory();
  } catch (e) {
    if (e.code === 'ENOENT') {
      return false;
    } else {
      throw e;
    }
  }
}
if (!isDirSync(myDir)) {
  fs.mkdirSync(myDir);
}

isDirSync方法为如果给定路径存在且为目录返回true,其他所有情况下将返回false。请注意如果遇到其他错误,它也会引发错误。实际上这不是必需的,因为据我所知,确实没有其他可能的错误,但是,你也许永远不知道!

ENOENT错误码表示fs.statSync抛出一个‘no such file or directory’错误。您需要检查这一点,因为与您期望的不同,检查不存在的路径的统计信息不会返回空stats对象,而是会导致函数失败并引发该错误。

您有时可能还会看到人们检查错误号而不是错误码。最好不要这样做,因为根据运行的Node版本或运行的操作系统的不同,错误号可能会有所不同。

Asynchronous exists

在异步世界中,可以使用fs.accessfs.stat替代fs.exists,开始看看吧。

fs.access

根据nodeback APIfs.access中的回调函数的第一个参数是错误对象,让我们再次检查目录是否已经存在并且创建它;

fs.access(myDir, function(err) {
  if (err && err.code === 'ENOENT') {
    fs.mkdir(myDir);
  }
});

请注意,我将检查错误和代码结合在一起。此特定解决方案的替代方法是先尝试使用fs.mkdir,如果目录已存在时将抛出错误码EEXIST

fs.stat

当然,我们还可以检查路径的统计信息,并根据结果决定要执行的操作。例如,让我们创建一个异步checkIfFile函数,该函数仅在给定路径存在且为文件的情况下返回true,而在所有其他情况下返回false

function checkIfFile(file, cb) {
  fs.stat(file, function(err, stats) {
    if (err) {
      if (err.code === 'ENOENT') {
        return cb(null, false);
      } else {
        return cb(err);
      }
    }
    return cb(null, stats.isFile());
  });
}
checkIfFile(aPath, function(err, isFile) {
  if (isFile) {
    // handle the file
  }
});

或者,使用Promise

function checkIfFile(file) {
  return new Promise(function(resolve, reject) {
    return fs.stat(file).then(function(stats) {
      resolve(stats.isFile());
    }).catch(function(err) {
      if (err.code === 'ENOENT') {
        resolve(false);
      } else {
        reject(err);
      }
    });
  });
}
checkIfFile(aPath).then(function(isFile) {
  if (isFile) {
    // handle the file
  }
}).catch(function(e) { throw e; });

所有做这些的目的不是要停留在完美替代fs.exists的细节上,而是要表明您可以使用比fs.exists更好的方法,而不是使用(不建议使用的方法)来实现您原本的目标。

但是我真的想要 fs.exists !!!

如果你想的话,可以继续使用!只需编写您自己的替换文件来代替fs.exists,或者引用社区里其他用户创建的。这个库是个很好的选择,不过您也可以随便挑选!


后记

这篇文章翻译于这里,也是我第一篇翻译的关于node的技术文章,是因为最近频繁的使用文件系统相关API,无意间看到这篇有点趣味性的原文,今天有点时间就翻译了一下,哈哈?

1daff6e87be68ea0de5bb7d36a9cb8cf.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值