動かざることバグの如し

近づきたいよ 君の理想に

Nodejs最新版でファイルの存在チェックをする

令和最新版Nodejsって響きよくないですか?

環境

  • Nodejs v14

概要

よくある、指定したパスのファイルが存在するかのチェック

いくつか方法があるのでメモ

【方法1】fs.existsSync()を使う

一番オーソドックスというか古典的。どのNodejsのバージョンでも実行できる。

const fs = require('fs')
if (fs.existsSync('/etc/passwd')) {
  console.log('The path exists.')
} else {
  console.log('The path not exists.')
}

メリットはコード数が少なくてシンプル、デメリットはSyncだからpromiseとの相性が良くないかも

ちなみに fs.exists()は非推奨なので注意

公式ドキュメントを確認しても、

Deprecated: Use fs.stat() or fs.access() instead.

って書いてある。使うな。あとQiitaとかでみんなよく勘違いしてるのが、上のfs.existsSync()は非推奨ではなく、現役でもぜんぜん使える。

【方法2】 fs.lstat() && stat.isFile()を使う

fs.exists()はpromise化できないので、async/awaitを使いたいって場合はこっち。

const fs = require('fs').promises
async function fileExists(filepath) {
  try {
    return !!(await fs.lstat(filepath))
  } catch (e) {
    return false
  }
}

fileExists('/etc/passwd')
  .then(res => console.log(res))

ポイントはasync/await使いたいので、requireを require('fs').promises にする必要がある点、fs.lstat()したときに、ファイルが存在しない場合例外が発生してしまう点。なので、今回はtry catchで囲って存在する場合はstat.isFile()でさらにチェックしてる。

単にディレクトリとかシンボリックリンク含めてパスが存在する場合だけ確認する場合は fs.lstat() である時点でtrue返せばいい。

ちなみに lstatの返り値のstatではファイルかどうかとかディレクトリかどうかといったチェックができるので、以下のように書くとディレクトリのときのみtrueといった処理がかける。

const fs = require('fs').promises
async function fileExists(filepath) {
  try {
    return (await fs.lstat(filepath)).isFile()
  } catch (e) {
    return false
  }
}

fileExists('/etc/')
  .then(res => console.log(res))

蛇足

fs.exists()が非推奨になった経緯は以下のサイトがとても詳しい。ちゃんとした理由があって納得した。

fs.exists()がdeprecatedになった理由 ¦ 学ぶ、考える、書き出す。