имя узла не определено


138

Из руководства по узлу я вижу, что могу получить каталог с файлом __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)


1
Я получил эту проблему при использовании eslint, я по ошибке установил "browser": trueвместо этого "node": trueв моем файле .eslintrc.json.
— Тойво Савен

Ответы:


187

__dirnameопределяется только в сценариях. Это не доступно в REPL.

попробуй сделать скрипт a.js

console.log(__dirname);

и запустить его:

node a.js

вы увидите __dirnameнапечатано.

Добавлено пояснение к фону: __dirnameозначает «Каталог этого скрипта». В REPL у вас нет сценария. Следовательно, __dirnameне будет иметь никакого реального значения.


5
Также вы не можете использовать некоторые глобальные переменные внутри модулей RequireJS. Если вы используете RequireJS на стороне сервера см stackoverflow.com/questions/9027429/... .
— Eye

1
Да, это действительно должно быть добавлено к ответу Eye, потому что это то, что меня достало.
— Томаш Зато - Восстановить Монику

3
Не добавлять это в сценарий загрузки REPL противно. Я не могу придумать ни одной причины, по которой этого не было бы ...
— jcollum

Я загрузил файл скрипта, используя REPL .load script.js. Жаль, что __dirname все еще недоступно из script.js
— Кевин Уилер

upvoted! сэкономил мне 15 минут, потому что я удивлялся, что происходит wtf
— PirateApp

96

Основываясь на существующих здесь ответах, вы можете определить это в своем REPL:

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

Или:

__dirname = path.resolve();

Если pathсегменты не переданы, path.resolve()вернется абсолютный путь к текущему рабочему каталогу.


Или альтернативы @Jthorpe:

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

если вы используете, neshвы можете определить это как часть вашего скрипта загрузки; это
— здорово

1
или __dirname = process.cwd()или __dirname=fs.realpathSync('.')или__dirname = process.env.PWD
— Jthorpe

1
path.dirnameпохоже, больше не принимает нестроковые значения в новейшей основной версии 6.0.0, поэтому первое предложение в этом ответе не сработает.
— trysis

30

В ES6 используйте:

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

также доступно, когда узел вызывается с --experimental-modules


Вам не нужно импортировать основные модули в REPL; он загрузит их на лету за вас.
— c24w

Это дает текущий рабочий каталог, а не каталог текущего .jsфайла.
— Dirbaio

@Dirbaio, каким будет текущий .jsфайл, когда вы находитесь в REPL?
— c24w,

@ c24w только что проверил, вроде
— выдает

@Dirbaio Я думаю, это была моя точка зрения. Когда вы входите в REPL, текущего файла JS нет. Кем бы вы хотели __dirnameбыть, если не CWD?
— c24w

8

Как сказал @qiao, вы не можете использовать __dirnameв узле repl. Однако, если вам нужно это значение в консоли, вы можете использовать path.resolve()или path.dirname(). Хотя, path.dirname()просто поставлю вам "." так что, вероятно, не очень полезно. Обязательно require('path').


3

Похоже, вы тоже могли бы это сделать:

__dirname=fs.realpathSync('.');

конечно, не забывай fs=require('fs')

(это не совсем глобально в сценариях узла, это просто определено на уровне модуля)


Вам не нужно требовать базовые модули в REPL; он загрузит их на лету за вас.
— c24w

3

Я также пытался присоединиться к своему пути, используя, path.join(__dirname, 'access.log')но он выдавал ту же ошибку.

Вот как я это исправил:

Сначала я импортировал пакет пути и объявил переменную с именем __dirname, а затем вызвал метод resolve пути .

В CommonJS

var path = require("path");

var __dirname = path.resolve();

В ES6 +

import path  from 'path';

const __dirname = path.resolve();

Удачного кодирования .......


2

Я запускал сценарий из командного файла как пользователь 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();

Если вы не запускаете это через REPL, вы можете использовать __dirnameи __filename.
— c24w

Это единственный ответ, который хотя бы пытается дать правильное решение.
— Томаш Зато - Восстановить Монику

@ c24w Я пробовал __dirname, __filename и все остальное. В моем случае стандартное решение не сработало. Вот мой проект, который запускает процесс как СИСТЕМУ из планировщика задач, если вам скучно github.com/DVLP/Unscheduler. Любое стандартное решение, которое в остальном работает, очевидно лучше, чем мой хак выше :)
— Павел

1

Хотя это не решение этой проблемы, я хотел бы добавить его, поскольку он может помочь другим.

Перед именем каталога должно быть два символа подчеркивания , а не один ( __dirnameнет _dirname).

NodeJS Docs


__dirname (с двумя символами подчеркивания) не работает в REPL
— Аарон Спетнер

1

Если вы получили node __dirname not definedс node --experimental-modules, вы можете сделать:

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

Потому что, например, работа только с текущим каталогом / pwd, а не с другим каталогом.


1

Если вы используете модули Node.js , __dirnameи __filenameне существует.

Из документации Node.js :

Не требуется, экспорт, module.exports, __filename, __dirname

Эти переменные CommonJS недоступны в модулях ES.

requireможно импортировать в модуль ES с помощью module.createRequire().

Эквиваленты __filenameи __dirnameмогут быть созданы внутри каждого файла с помощью import.meta.url:

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


0

иногда мы делаем файл с расширением .js и добавляем consol.log (_dirname); но мы сталкиваемся с ошибками, мы торопимся, поэтому мы забываем добавить еще один символ подчеркивания перед словом «dirname», поэтому мы сталкиваемся с ошибкой ссылки. Правильный синтаксис - consol.log (__ dirname);

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.