如何使用Node.js获取当前脚本的路径?

How do I get the path to the current script with Node.js?

如何获取node.js中脚本的路径?

我知道有process.cwd,但这只指调用脚本的目录,而不是脚本本身。例如,假设我在/home/kyle/中,我运行以下命令:

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

如果我叫process.cwd(),我就得到/home/kyle/,而不是/home/kyle/some/dir/。有没有办法得到那个目录?


我又看了一遍文件后发现了它。我要找的是__filename__dirname模块级变量。

  • __filename是当前模块的文件名。这是当前模块文件的解析绝对路径。(例如:/home/kyle/some/dir/file.js)
  • __dirname是当前模块的目录名。(例如:/home/kyle/some/dir)


所以基本上你可以这样做:

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

使用resolve()而不是与"/"或""连接,否则会遇到跨平台问题。

注意:uu dirname是模块或包含脚本的本地路径。如果您正在编写一个需要知道主脚本路径的插件,它是:

1
require.main.filename

或者,只需获取文件夹名称:

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


此命令返回当前目录:

1
var currentPath = process.cwd();

例如,要使用路径读取文件:

1
2
3
4
5
6
7
8
var fs = require('fs');
fs.readFile(process.cwd() +"\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});


请使用!!

1
__dirname

当前模块的目录名。这与__filename的path.dirname()相同。

示例:从/users/mjr运行node example.js

1
2
3
4
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

https://nodejs.org/api/modules.html模块目录名

对于要使用的E模块:import.meta.url


当涉及到主脚本时,它简单如下:

1
process.argv[1]

从node.js文档中:

process.argv

An array containing the command line arguments. The first element will be 'node', the second element will be the path to the JavaScript file. The next elements will be any additional command line arguments.

如果需要知道模块文件的路径,请使用文件名。


1
2
3
4
5
6
7
var settings =
    JSON.parse(
        require('fs').readFileSync(
            require('path').resolve(
                __dirname,
                'settings.json'),
            'utf8'));


每个node.js程序在其环境中都有一些全局变量,这些变量表示一些关于进程的信息,其中一个变量是__dirname


node.js 10支持ecmascript模块,其中__dirname__filename不再可用。

然后,要获得当前ES模块的路径,必须使用:

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

对于包含当前模块的目录:

1
2
3
import path from 'path';

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


我知道这很古老,我回答的原始问题被标记为副本并指向此处,但我遇到了一个问题,试图让茉莉花记者工作,不喜欢我不得不降级才能使其工作的想法。我发现jasmine reporters没有正确解析存储路径,实际上是将报告文件夹输出放在jasmine reporters目录中,而不是运行gulp的根目录中。为了使这个正确工作,我最终使用了process.env.init_cwd来获取初始的当前工作目录,该目录应该是运行gulp的目录。希望这能帮助别人。

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


可以使用process.env.pwd获取当前应用程序文件夹路径。


如果您使用pkg打包应用程序,您会发现这个表达式很有用:

1
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]获取节点可执行文件的路径,或使用process.cwd()获取当前目录。


使用path模块的basename方法:

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

以下是上述示例的文档。

正如丹指出的那样,node正在使用带有"-experimental modules"标志的ecmascript模块。节点12仍然支持上述的__dirname__filename

如果您使用的是--experimental-modules标志,则有一种替代方法。

另一种方法是获取当前ES模块的路径:

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

对于包含当前模块的目录:

1
2
3
import path from 'path';

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

如果您想在shell脚本中使用更像$0的内容,请尝试以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
    }
}