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

Kyl*_*ery 921 node.js

我如何获得Node.js中脚本的路径?

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

node /home/kyle/some/dir/file.js
Run Code Online (Sandbox Code Playgroud)

如果我打电话process.cwd(),我会/home/kyle/,而不是/home/kyle/some/dir/.有办法获得该目录吗?

Kyl*_*ery 1321

我再次查看了文档后找到了它.我正在寻找的是__filename__dirname模块级变量.

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

  • @AnthonyMartin __dirname.split("/").pop() (57认同)
  • 或者`require('path').basename(__ dirname);` (47认同)
  • 或者只是`__dirname.split(path.sep).pop()` (34认同)
  • 这[不再适用于 ES 模块](/sf/ask/219327041/# 50053801)。 (13认同)
  • 对于那些尝试@apx解决方案(就像我做:),这个解决方案在Windows上不起作用. (6认同)
  • 如果只需要目录名而不是完整路径,则可以执行以下操作:function getCurrentDirectoryName(){var fullPath = __dirname; var path = fullPath.split('/'); var cwd = path [path.length-1]; 返回cwd; } (3认同)
  • @VeaceslavCotruta评论肯定是最好的解决方案. (3认同)

Mar*_*arc 236

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

fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);
Run Code Online (Sandbox Code Playgroud)

使用resolve()而不是与'/'或'\'连接,否则您将遇到跨平台问题.

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

require.main.filename
Run Code Online (Sandbox Code Playgroud)

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

require('path').dirname(require.main.filename)
Run Code Online (Sandbox Code Playgroud)

  • 如果你的目标只是解析json文件并与之交互,你通常可以通过`var settings = require('./ settings.json')`更容易地做到这一点.当然,它是同步的fs IO,所以不要在运行时这样做,但是在启动时它很好,一旦它被加载,它将被缓存. (14认同)
  • 这[不再适用于 ES 模块](/sf/ask/219327041/# 50053801)。 (3认同)
  • @Marc谢谢!有一段时间我现在正在讨论__dirname是每个模块的本地事实.我的库中有一个嵌套结构,需要在几个地方知道我的应用程序的根目录.很高兴我现在知道如何做到这一点:D (2认同)

Mas*_*ali 101

此命令返回当前目录:

var currentPath = process.cwd();
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这正是OP不想要的......请求是针对可执行脚本的路径! (10认同)
  • 当前目录是一个非常不同的东西。如果你运行类似`cd /foo; node bar/test.js`,当前目录是`/foo`,但脚本位于`/foo/bar/test.js`。 (5认同)
  • 你为什么要这么做?如果该文件相对于当前目录,您只需读取“text.txt”即可工作,无需构建绝对路径 (3认同)
  • 这不是一个好的答案。这是逻辑混乱的,因为这可能比你预期的要短得多。 (2认同)

Aza*_*rus 84

使用__dirname !!

__dirname
Run Code Online (Sandbox Code Playgroud)

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

示例:从/ Users/mjr运行节点example.js

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
Run Code Online (Sandbox Code Playgroud)

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

  • 这个答案不仅是多年前给出的,它还[不再适用于 ES 模块](/sf/ask/219327041/脚本与节点 js/50053801#50053801)。 (3认同)
  • 这也能在符号链接中幸存下来。因此,如果您创建一个 bin 并需要查找一个文件,例如 path.join(__dirname, "../example.json"); 当您的二进制文件链接到 node_modules/.bin 中时它仍然可以工作 (2认同)

Luk*_*tor 47

说到主脚本,它很简单:

process.argv[1]
Run Code Online (Sandbox Code Playgroud)

Node.js文档:

process.argv

包含命令行参数的数组.第一个元素是'node',第二个元素是JavaScript文件的路径.下一个元素将是任何其他命令行参数.

如果您需要知道模块文件的路径,请使用__filename.

  • 如果使用节点进程管理器(如pm2)启动主脚本,则process.argv [1]将指向进程管理器的可执行文件/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js (10认同)
  • 请问downvoter请解释为什么不建议这样做? (3认同)
  • @Tamlyn 也许是因为 `process.argv[1]` 仅适用于主脚本,而 `__filename` 指向正在执行的模块文件。我更新了我的答案以强调差异。尽管如此,我认为使用 `process.argv[1]` 没有任何问题。看个人要求。 (3认同)

小智 28

var settings = 
    JSON.parse(
        require('fs').readFileSync(
            require('path').resolve(
                __dirname, 
                'settings.json'),
            'utf8'));
Run Code Online (Sandbox Code Playgroud)

  • 只需注意,从节点0.5开始,您只需要一个JSON文件即可.当然,这不会回答这个问题. (7认同)
  • `__dirname` [不再适用于 ES 模块](/sf/ask/219327041/ 50053801#50053801)。 (2认同)

Haz*_*yan 24

每个Node.js程序在其环境中都有一些全局变量,它代表了有关您的进程的一些信息,其中之一就是__dirname.

  • 这个答案不仅是几年前给出的,`__dirname` [不再适用于 ES 模块](/sf/ask/219327041/ -script-with-node-js/50053801#50053801)。 (2认同)

GOT*_*O 0 24

Node.js 10支持ECMAScript模块,其中__dirname__filename开箱即用.

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

import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
Run Code Online (Sandbox Code Playgroud)

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

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

const __dirname = dirname(fileURLToPath(import.meta.url));
Run Code Online (Sandbox Code Playgroud)

  • 仅当您运行的节点版本 < 13.2 时才需要 --experimental-modules。只需将文件命名为 .mjs 而不是 .js (5认同)
  • ES 模块仅在带有 `--experimental-modules` 标志的情况下可用。 (2认同)
  • 是的,这有效。@Nickensoul 或在 package.json "type": "module", (2认同)

小智 14

NodeJS 公开了一个名为 的全局变量__dirname

__dirname返回 JavaScript 文件所在文件夹的完整路径。

因此,以 Windows 为例,如果我们创建一个包含以下行的脚本文件:

console.log(__dirname);
Run Code Online (Sandbox Code Playgroud)

并使用以下命令运行该脚本:

node ./innerFolder1/innerFolder2/innerFolder3/index.js
Run Code Online (Sandbox Code Playgroud)

输出将为: C:\Users...<项目目录>\innerFolder1\innerFolder2\innerFolder3


Dan*_*ris 12

我知道这是相当陈旧的,我回答的原始问题被标记为重复并指示在这里,但我遇到了一个问题,试图让茉莉花 - 记者工作,并且不喜欢我不得不降级的想法为了它的工作.我发现jasmine-reporter没有正确解析savePath,实际上是将报告文件夹输出放在jasmine-reporter目录而不是我运行gulp的根目录.为了使这项工作正常,我最终使用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
 });
Run Code Online (Sandbox Code Playgroud)


Abi*_*vam 7

您可以使用process.env.PWD获取当前的应用程序文件夹路径.

  • OP要求提供所请求的“脚本路径”。PWD代表“进程工作目录”之类的东西,并非如此。同样,“当前应用”的措词具有误导性。 (2认同)

dmc*_*dor 7

如果您pkg用于打包应用程序,则该表达式会很有用:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
Run Code Online (Sandbox Code Playgroud)
  • process.pkg告诉应用程序是否已被打包pkg

  • process.execPath保留可执行文件的完整路径,/usr/bin/node对于直接调用脚本(node test.js)或打包的应用程序,该路径是相似的。

  • require.main.filename 保留主脚本的完整路径,但是当Node在交互模式下运行时,该路径为空。

  • __dirname包含当前脚本的完整路径,因此我不使用它(尽管这可能是OP要求的;然后最好使用appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));它,在交互模式下请注意__dirname是空的。

  • 对于交互模式,请使用process.argv[0]获取Node可执行文件的路径或process.cwd()获取当前目录。


Mic*_*ole 6

使用模块的basename方法path

var path = require('path');
var filename = path.basename(__filename);
console.log(filename);
Run Code Online (Sandbox Code Playgroud)

是上述示例取自的文档。

正如 Dan 所指出的,Node 正在开发带有“--experimental-modules”标志的ECMAScript 模块。Node 12 仍然支持__dirname__filename如上。


如果您正在使用该--experimental-modules标志,则有另一种方法

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

const __filename = new URL(import.meta.url).pathname;
Run Code Online (Sandbox Code Playgroud)

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

import path from 'path';

const __dirname = path.dirname(new URL(import.meta.url).pathname);
Run Code Online (Sandbox Code Playgroud)