如何在 Node.js 中获取脚本的路径?
我知道有 process.cwd
,但这只是指调用脚本的目录,而不是脚本本身。例如,假设我在 /home/kyle/
中并运行以下命令:
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)
所以基本上你可以这样做:
fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);
使用 resolve() 而不是连接 '/' 或 '\' 否则你会遇到跨平台问题。
注意:__dirname 是模块或包含脚本的本地路径。如果您正在编写一个需要知道主脚本路径的插件,它是:
require.main.filename
或者,仅获取文件夹名称:
require('path').dirname(require.main.filename)
var settings = require('./settings.json')
更轻松地做到这一点。当然是同步fs IO,所以不要在运行时做,但在启动时就可以了,一旦加载,就会被缓存。
//////home//////yourname///////
是一个有效的路径),但是如果您假设路径是否会有结束斜杠,那么在某些情况下,不负责任地使用连接可能会导致某些内容不可读,或者如果斜杠意外地附加到 /home/yourname/yourfile.png/ 之类的文件名
使用 __dirname!!
__dirname
当前模块的目录名。这与 __filename
的 path.dirname() 相同。
示例:从 /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
对于您想要使用的 ESModules:import.meta.url
此命令返回当前目录:
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());
});
cd /foo; node bar/test.js
之类的东西,当前目录将是 /foo
,但脚本位于 /foo/bar/test.js
。
text.txt
并且它会工作,您不需要构造绝对路径
Node.js 10 支持 ECMAScript modules,其中 __dirname
and __filename
are no longer available。
然后要获得 path to the current ES module 必须使用:
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));
--experimental-modules
标志。
当涉及到主脚本时,它很简单:
process.argv[1]
process.argv 包含命令行参数的数组。第一个元素是“节点”,第二个元素是 JavaScript 文件的路径。下一个元素将是任何附加的命令行参数。
如果您需要知道模块文件的路径,请使用 __filename。
process.argv[1]
仅适用于主脚本,而 __filename
指向正在执行的模块文件。我更新了我的答案以强调差异。不过,我认为使用 process.argv[1]
没有任何问题。取决于一个人的要求。
var settings =
JSON.parse(
require('fs').readFileSync(
require('path').resolve(
__dirname,
'settings.json'),
'utf8'));
__dirname
no longer works with ES modules。
每个 Node.js 程序在其环境中都有一些全局变量,它们代表有关您的进程的一些信息,其中之一是 __dirname
。
__dirname
no longer works with ES modules。
我知道这已经很老了,我回答的原始问题被标记为重复并指向此处,但我遇到了一个试图让 jasmine-reporters 工作的问题,并且不喜欢我不得不降级的想法命令它工作。我发现 jasmine-reporters 没有正确解析 savePath
,实际上是将报告文件夹输出放在 jasmine-reporters 目录中,而不是我运行 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
});
您可以使用 process.env.PWD 来获取当前的应用程序文件夹路径。
如果您使用 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 或类似的直接调用脚本(节点 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() 获取当前目录。
使用 path
模块的 basename
方法:
var path = require('path');
var filename = path.basename(__filename);
console.log(filename);
Here 是上述示例的文档。
正如 Dan 指出的那样,Node 正在使用“--experimental-modules”标志处理 ECMAScript modules。节点 12 仍为 supports __dirname
and __filename
,如上。
如果您使用 --experimental-modules
标志,则有一个 alternative approach。
另一种方法是获取 path to the current ES module:
const __filename = new URL(import.meta.url).pathname;
对于包含当前模块的目录:
import path from 'path';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
NodeJS 公开了一个名为 __dirname
的全局变量。
__dirname
返回 JavaScript 文件所在文件夹的完整路径。
因此,例如,对于 Windows,如果我们使用以下行创建一个脚本文件:
console.log(__dirname);
并使用以下命令运行该脚本:
node ./innerFolder1/innerFolder2/innerFolder3/index.js
输出将是:C:\Users...
包含要导出的模块的任何文件夹中的 index.js
const entries = {};
for (const aFile of require('fs').readdirSync(__dirname, { withFileTypes: true }).filter(ent => ent.isFile() && ent.name !== 'index.js')) {
const [ name, suffix ] = aFile.name.split('.');
entries[name] = require(`./${aFile.name}`);
}
module.exports = entries;
这将在当前目录的根目录中找到所有文件,要求并导出与文件名词干具有相同导出名称的每个文件。
如果你想在 shell 脚本中得到更像 $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.split(path.sep).pop()
require('path').basename(__dirname);