Node.jsを使用して現在のスクリプトへのパスを取得するにはどうすればよいですか?


979

Node.jsでスクリプトへのパスを取得するにはどうすればよいですか?

があることは知っprocess.cwdていますが、これはスクリプト自体ではなく、スクリプトが呼び出されたディレクトリのみを指します。たとえば/home/kyle/、次のコマンドを実行するとします。

node /home/kyle/some/dir/file.js

私が呼び出す場合process.cwd()、私が取得し/home/kyle/、ありません/home/kyle/some/dir/。そのディレクトリを取得する方法はありますか?


6
nodejs.org/docs/latest/api/globals.html承認された回答のドキュメントリンク。
allenhwkim 2013

回答:


1393

もう一度ドキュメントを調べてみました。私が探していたのは、__filenameおよび__dirnameモジュールレベルの変数です。

  • __filename現在のモジュールのファイル名です。これは、現在のモジュールファイルの解決された絶対パスです。(例:/home/kyle/some/dir/file.js
  • __dirname現在のモジュールのディレクトリ名です。(例:/home/kyle/some/dir

3
フルパスではなくディレクトリ名のみが必要な場合は、次のようにします。function getCurrentDirectoryName(){var fullPath = __dirname; var path = fullPath.split( '/'); var cwd = path [path.length-1]; cwdを返します。}
アンソニーマーティン

58
。__dirname.split @AnthonyMartin( "/")()ポップ
19H

6
(私がしたように)@apxソリューションを試す人にとって、このソリューションはWindowsでは機能しません。
ラウジン、2015年

36
または単に__dirname.split(path.sep).pop()
Burgi

47
またはrequire('path').basename(__dirname);
Vyacheslav Cotruta

251

だから基本的にこれを行うことができます:

fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);

'/'または '\'で連結する代わりにresolve()を使用してください。そうしないと、クロスプラットフォームの問題が発生します。

注:__dirnameは、モジュールまたは含まれているスクリプトのローカルパスです。メインスクリプトのパスを知る必要があるプラグインを作成している場合は、次のようになります。

require.main.filename

または、単にフォルダ名を取得するには:

require('path').dirname(require.main.filename)

16
目的がjsonファイルを解析して操作することだけである場合は、多くの場合、を使用してこれをより簡単に行うことができますvar settings = require('./settings.json')。もちろん、これは同期fs IOなので、実行時には行わないでください。ただし、起動時には問題なく、一度読み込まれるとキャッシュされます。
isaacs

2
@マルクありがとう!しばらくの間、私は__dirnameが各モジュールに対してローカルであるという事実を回避する方法を模索していました。ライブラリにネストされた構造があり、いくつかの場所でアプリのルートを知る必要があります。私は今これを行う方法を知ってうれしい:D
Thijs Koerselman '28

ノードV8:path.dirname(process.mainModule.filename)
wayofthefuture 2017

Windowsを実際のプラットフォームと見なさない場合、解決をスキップできますか?BSD、Macos、linux、tizen、symbian、Solaris、android、flutter、webosすべて使用/正しいですか?
レイ・フォス


119

次のコマンドは、現在のディレクトリを返します。

var currentPath = process.cwd();

たとえば、パスを使用してファイルを読み取るには、次のようにします。

var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});

AsynchronousSynchronousを理解していない人は、このリンクを参照してください... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
これはまさにOPが望まないことです...要求は実行可能スクリプトのパスに対するものです!
シーザーソル

3
現在のディレクトリは非常に異なります。のようなものを実行するとcd /foo; node bar/test.js、現在のディレクトリはになります/fooが、スクリプトはにあり/foo/bar/test.jsます。
rjmunro

それは良い答えではありません。これは、論理的な混乱を招くので、予想よりもはるかに短いパスになる可能性があります。
kris_IV

なぜこれをやるのですか?ファイルが現在のディレクトリに相対した場合は、単に読むことができたtext.txtし、それが働くだろう、あなたは絶対パスを構築する必要はありません
マイケルMrozek

104

__dirnameを使用してください!!

__dirname

現在のモジュールのディレクトリ名。これはのpath.dirname()と同じ__filenameです。

例:/ users / mjrからノードexample.jsを実行する

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

https://nodejs.org/api/modules.html#modules_dirname

ESModuleの場合、次のように使用します。 import.meta.url


1
これはシンボリックリンクでも生き残ります。したがって、ビンを作成してファイルを見つける必要がある場合は、たとえば、path.join(__ dirname、 "../example.json"); バイナリがnode_modules / .binにリンクされている場合でも機能します
Jason

2
この回答は数年前に与えられただけでなく、ESモジュールでも機能しなくなりました
Dan Dascalescu

48

メインスクリプトに関しては、次のように簡単です。

process.argv[1]

Node.jsのドキュメントから:

process.argv

コマンドライン引数を含む配列。最初の要素は「ノード」、2番目の要素はJavaScriptファイルへのパスになります。次の要素は、追加のコマンドライン引数です。

モジュールファイルのパスを知る必要がある場合は、__filenameを使用します


3
反対投票者は、これが推奨されない理由を説明できますか?
Tamlyn

1
@Tamlynたぶん、実行中のモジュールファイルprocess.argv[1]__filenameポイントしながら、メインスクリプトにのみ適用されます。違いを強調するために回答を更新します。それでも、の使用には何の問題もありませんprocess.argv[1]。自分の要件に依存します。
Lukasz Wiktor

10
メインスクリプトがpm2 process.argv [1]などのノードプロセスマネージャーで起動された場合、プロセスマネージャーの実行可能ファイルをポイントします/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

10個のサポートのNode.js のECMAScriptモジュール__dirnameおよび__filename使用可能でなくなりました

次に、現在のESモジュールへパスを取得するには、次のコマンドを使用する必要があります。

import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);

そして、現在のモジュールを含むディレクトリについて:

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

ESモジュールを作成しているかどうかはどうすればわかりますか?実行しているNodeのバージョンの問題なのでしょうか、それともimport / exportキーワードを使用しているのですか?
Ed Brannin

2
ESモジュールは--experimental-modulesフラグ付きでのみ使用できます。
Nickensoul

1
--experimental-modulesは、ノードのバージョンが13.2未満の場合にのみ必要です。ファイルに.jsではなく.mjsという名前を付けるだけ
ブレント


24

すべてのNode.jsプログラムには、その環境内にいくつかのグローバル変数があります。これは、プロセスに関するいくつかの情報を表し、その1つはです__dirname


この回答が数年前に与えられただけで__dirname なく、ESモジュールでも機能しなくなりました
Dan Dascalescu

それはNodeJs 10についてですが、この答えは、2016年に出版された
Hazarapet Tunanyan

知っている。テクノロジーの変更に応じて回答を更新できます。
Dan Dascalescu、

13

私はこれがかなり古いことを知っており、私が応答していた元の質問は重複としてマークされ、ここで指示されましたが、ジャスミンレポーターを機能させようとする問題に遭遇し、ダウングレードする必要があるという考えが気に入りませんでした機能するように注文します。jasmine-reportersがsavePathを正しく解決しておらず、実際にレポートフォルダーの出力を、gulpを実行したルートディレクトリではなくjasmine-reportersディレクトリに置いていることがわかりました。これを正しく機能させるために、私はprocess.env.INIT_CWDを使用しgulpを実行したディレクトリである最初の現在の作業ディレクトリを取得することになりました。これが誰かを助けることを願っています。

var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
  savePath: process.env.INIT_CWD + '/report/e2e/',
  consolidateAll: true,
  captureStdout: true
 });

8

現在のアプリのフォルダーパスを取得するには、process.env.PWDを使用できます。


2
OPは、要求された「スクリプトへのパス」を要求します。PWDは、Process Working Directoryなどの略ですが、そうではありません。また、「現在のアプリ」の表現は誤解を招くものです。
dmcontador 2017

7

pkgアプリのパッケージ化に使用している場合は、次の式が便利です。

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkgアプリがによってパッケージ化されているかどうかを通知しpkgます。

  • process.execPath実行可能ファイルのフルパスを保持します。これは/usr/bin/node、スクリプト(node test.js)またはパッケージ化されたアプリを直接呼び出す場合と同様です。

  • require.main.filename メインスクリプトの完全パスを保持しますが、ノードがインタラクティブモードで実行されている場合は空です。

  • __dirname現在のスクリプトの完全なパスを保持しているので、私はそれを使用しません(OPが要求するものかもしれませんappDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));が、インタラクティブモードで__dirnameは空であることに注意してください)。

  • 対話モードの場合process.argv[0]、Node実行可能ファイルへのパスを取得するかprocess.cwd()、現在のディレクトリを取得するために使用します。


3

モジュールのbasenameメソッドを使用しpathます。

var path = require('path');
var filename = path.basename(__filename);
console.log(filename);

ここに、上記の例から取られているマニュアルです。

Danが指摘したように、Nodeは「--experimental-modules」フラグ付きのECMAScriptモジュールに取り組んでいます。ノード12 __dirname__filename上記をサポートています。


--experimental-modulesフラグを使用している場合は、別の方法があります。

別の方法は、現在のESモジュールへのパスを取得することです

const __filename = new URL(import.meta.url).pathname;

そして、現在のモジュールを含むディレクトリについて:

import path from 'path';

const __dirname = path.dirname(new URL(import.meta.url).pathname);

-2

シェルスクリプトで$ 0のようなものがもっと必要な場合は、以下を試してください。

var path = require('path');

var command = getCurrentScriptPath();

console.log(`Usage: ${command} <foo> <bar>`);

function getCurrentScriptPath () {
    // Relative path from current working directory to the location of this script
    var pathToScript = path.relative(process.cwd(), __filename);

    // Check if current working dir is the same as the script
    if (process.cwd() === __dirname) {
        // E.g. "./foobar.js"
        return '.' + path.sep + pathToScript;
    } else {
        // E.g. "foo/bar/baz.js"
        return pathToScript;
    }
}

__dirnameそして、__filenameされていないESモジュールで使用できなくなります
Dan Dascalescu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.