节点__dirname未定义

时间:2012-01-11 10:05:47

标签: node.js

从节点手册中我看到我可以使用__dirname获取文件的目录,但是从REPL看,这似乎是未定义的。这是对我的误解还是错误在哪里?

$ node
> console.log(__dirname)
ReferenceError: __dirname is not defined
    at repl:1:14
    at REPLServer.eval (repl.js:80:21)
    at Interface.<anonymous> (repl.js:182:12)
    at Interface.emit (events.js:67:17)
    at Interface._onLine (readline.js:162:10)
    at Interface._line (readline.js:426:8)
    at Interface._ttyWrite (readline.js:603:14)
    at ReadStream.<anonymous> (readline.js:82:12)
    at ReadStream.emit (events.js:88:20)
    at ReadStream._emitKey (tty.js:320:10)

11 个答案:

答案 0 :(得分:152)

__dirname仅在脚本中定义。它在REPL中不可用。

尝试制作一个脚本a.js

console.log(__dirname);

并运行它:

node a.js

您会看到__dirname已打印。

添加了背景说明:__dirname表示“此脚本的目录”。在REPL中,您没有脚本。因此,__dirname没有任何实际意义。

答案 1 :(得分:64)

在此处基于现有答案,您可以在REPL中定义:

__dirname = path.resolve(path.dirname(''));

或者:

__dirname = path.resolve();
  

If no path segments are passed, path.resolve() will return the absolute path of the current working directory.


或@ Jthorpe的替代方案:

__dirname = process.cwd();
__dirname = fs.realpathSync('.');
__dirname = process.env.PWD

答案 2 :(得分:25)

如果您使用的是 Node.js modules ,则__dirname__filename不存在。

来自Node.js documentation

不需要,导出,module.exports,__ filename,__ dirname

这些CommonJS变量在ES模块中不可用。

require可以使用module.createRequire()导入ES模块。

可以通过import.meta.url在每个文件内部创建__filename__dirname的等效项:

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

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

https://nodejs.org/api/esm.html#esm_no_require_exports_module_exports_filename_dirname

答案 3 :(得分:8)

在ES6中使用:

import path from 'path';
const __dirname = path.resolve();

在用--experimental-modules调用节点时也可用

答案 4 :(得分:7)

我还试图使用path.join(__dirname, 'access.log')加入我的路径,但是它抛出了相同的错误。

这是我的固定方法:

我首先导入了 path 包,并声明了一个名为__dirname的变量,然后称为resolve path 方法。

在CommonJS中

var path = require("path");

var __dirname = path.resolve();

在ES6 +中

import path  from 'path';

const __dirname = path.resolve();

快乐的编码。……

答案 5 :(得分:5)

正如@qiao所说,你不能在节点repl中使用__dirname。但是,如果您需要在控制台中使用此值,则可以使用path.resolve()path.dirname()。虽然,path.dirname()只会给你一个&#34;。&#34;所以,可能没那么有用。请务必require('path')

答案 6 :(得分:4)

-> 在 ES6 版本使用:

import path from "path"
const __dirname = path.resolve();

-> 像这样使用它,例如:

res.sendFile(path.join(__dirname ,'views','shop.html'))

答案 7 :(得分:2)

好像你也可以这样做:

__dirname=fs.realpathSync('.');

当然,不要忘记fs=require('fs')

(它在节点脚本中并不是真正的全局,它只是在模块级别定义)

答案 8 :(得分:2)

如果您将node __dirname not definednode --experimental-modules一起使用,则可以执行以下操作:

const __dirname = path.dirname(import.meta.url)
                      .replace(/^file:\/\/\//, '') // can be usefull

由于该示例,仅适用于当前/ pwd目录,而不适用于其他目录。

答案 9 :(得分:1)

虽然它不是这个问题的解决方案,但我想添加它,因为它可以帮助其他人。

在dirname之前你应该有两个下划线不是一个下划线__dirname而不是_dirname)。

http://nodejs.org/docs/latest/api/globals.html#globals_dirname

答案 10 :(得分:1)

我从批处理文件中以SYSTEM用户身份运行脚本,所有变量(如process.cwd()path.resolve()和所有其他方法都会为我提供C:\ Windows \ System32文件夹而不是实际路径的路径。在实验期间,我注意到当抛出错误时,堆栈包含节点文件的真实路径。

这是一种通过触发错误并从e.stack中提取路径来获得真实路径的非常黑客的方法。不要使用。

// this should be the name of currently executed file
const currentFilename = 'index.js';

function veryHackyGetFolder() {
  try {
    throw new Error();
  } catch(e) {
    const fullMsg = e.stack.toString();
    const beginning = fullMsg.indexOf('file:///') + 8;
    const end = fullMsg.indexOf('\/' + currentFilename);
    const dir = fullMsg.substr(beginning, end - beginning).replace(/\//g, '\\');
    return dir;
  }
}

用法

const dir = veryHackyGetFolder();