从节点手册中,我看到我可以用__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)

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

尝试编写一个a.js脚本

console.log(__dirname);

然后运行它:

node a.js

你会看到打印出__dirname。

增加了后台解释:__dirname表示“此脚本的目录”。在REPL中,您没有脚本。因此,__dirname将没有任何实际意义。


正如@qiao所说,你不能在节点repl中使用__dirname。但是,如果你需要在控制台中使用这个值,你可以使用path.resolve()或path.dirname()。虽然,path.dirname()只会给你一个“。”,所以,可能没有那么有用。确保require('path')。


在现有答案的基础上,你可以在你的REPL中定义这个:

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

Or:

__dirname = path.resolve();

如果没有传递路径段,path.resolve()将返回当前工作目录的绝对路径。


或者@Jthorpe的替代方案:

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

似乎你还可以这样做:

__dirname=fs.realpathSync('.');

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

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


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

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

NodeJS 文档


我以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();

在ES6中使用:

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

在使用——experimental-modules调用node时也可用


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

以下是我的解决方法:

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

在CommonJS

var path = require("path");

var __dirname = path.resolve();

在ES6 +

import path  from 'path';

const __dirname = path.resolve();

编码快乐……


如果node——experimental-modules没有定义node__dirname,你可以这样做:

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

因为其他的例子,工作只与当前/pwd目录,而不是其他目录。


如果你正在使用Node.js模块,__dirname和__filename不存在。

来自Node.js文档:

不需要,导出,模块。导出,__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/docs/latest-v15.x/api/esm.html#esm_no_filename_or_dirname


->在ES6版本使用:

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

然后像这样使用它:

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