Node.jsのprocess.cwd()で作業ディレクトリ取得

Node.jsで作業ディレクトリの絶対パスを取得するには、process.cwd()を使います。戻り値は「Node.jsを起動したディレクトリ」であり、実行しているスクリプトファイルの場所ではありません。この違いを押さえておくと、パス関連のトラブルの大半を避けられます。

こんな悩みを解決します

  • ENOENT: no such file or directoryでファイルを読み込めないエラー
  • 手元では動くのにサーバーやCIで動かない問題
  • プログラムの基準ディレクトリが分からない状況
  • process.cwd()と__dirnameの使い分け

process.cwd()とは

process.cwd()は、現在の作業ディレクトリ(カレントディレクトリ)の絶対パスを文字列で返すメソッドです。作業ディレクトリとは、ターミナルで「今いる場所」のことです。cwdは current working directory の略です。

process.cwd()

返ってくる値は実行環境によって次のように変わります。

  • Windows: C:\Users\taro\projectのような形式
  • macOS・Linux: /home/taro/projectのような形式

ファイルの読み書きやパスの組み立てでは、基準になるディレクトリを把握することが重要です。process.cwd()をログに出せば、プログラムがどこを基準に動いているかをすぐに確認できます。

戻り値は「スクリプトの場所」ではない

process.cwd()が返すのは、nodeコマンドを実行した場所です。スクリプトファイルが置かれている場所とは関係ありません。
たとえば、/home/taro/projectにいる状態でsrcフォルダ内のスクリプトを実行したとします。この場合、process.cwd()が返すのは/home/taro/projectです。スクリプトがある/home/taro/project/srcにはなりません。
同じスクリプトでも、どこから実行するかで結果が変わります。これが「自分のPCでは動くのに、別の環境では動かない」という現象の主な原因です。

スクリプトの場所を知りたいときは__dirname

スクリプトファイル自身のあるディレクトリが必要な場合は、__dirnameを使います。process.cwd()との違いは次のとおりです。

項目 process.cwd() __dirname
意味 Node.jsを起動したディレクトリ 実行中のファイルがあるディレクトリ
実行場所による変化 変わる 変わらない
向いている用途 実行したプロジェクトのルートを基準にしたい場合 スクリプトと同じ場所のファイルを参照したい場合

ES Modules(import構文を使う形式)では__dirnameが使えません。Node.js 20.11以降ならimport.meta.dirnameが代わりになります。それ以前のバージョンでは、import.meta.urlからfileURLToPathで変換します。

相対パスでファイルが見つからない原因

fs.readFile('./data.json')のような相対パスは、スクリプトの場所ではなくprocess.cwd()を基準に解決されます。そのため、実行場所が変わると同じコードでもENOENTになります。
対処法は、基準を明示した絶対パスを組み立てることです。

  • スクリプトと同じ場所にあるファイル: path.join(__dirname, 'data.json')で指定
  • 実行したプロジェクトのルートにあるファイル: path.join(process.cwd(), 'data.json')で指定

path.joinやpath.resolveを使えば、/と\の違いを意識せずに済みます。文字列を+で連結するより安全です。path.resolve('data.json')は、process.cwd()を基準にした絶対パスを返します。

使い分けの目安

  • 設定ファイルやテンプレートなど、スクリプトに同梱するファイル: __dirname
  • CLIツールが、利用者のプロジェクト内のファイルを探す場合: process.cwd()
  • 実行場所に左右されたくない処理全般: __dirnameを基準にした指定

注意点

作業ディレクトリが意図せず変わるケースは次のとおりです。

  • process.chdir()の呼び出しによる、以降のprocess.cwd()の値の変化
  • VS Codeのデバッグ実行、cron、タスクスケジューラ、DockerのWORKDIRなど、手元の実行と起動時の作業ディレクトリが異なる環境

動作が環境ごとに食い違うときは、まずprocess.cwd()をログに出力して、実際の基準位置を確認してください。

まとめ

  • process.cwd()の戻り値は、Node.jsを起動したディレクトリの絶対パス
  • スクリプト自身の場所が必要なときの選択肢は__dirname
  • 相対パスの基準はprocess.cwd()で、実行場所が変わるとエラーになること
  • path.joinやpath.resolveによるパスの組み立てで、環境差のトラブルを軽減
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です