вузол __ імені не визначено


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.
— Toivo Säwén

Відповіді:


187

__dirnameвизначається лише в сценаріях. Це недоступно в системі REPL.

спробуйте зробити сценарій a.js

console.log(__dirname);

і запустіть його:

node a.js

ви побачите __dirnameнадруковані.

Додано додаткове пояснення: __dirnameозначає "Каталог цього сценарію". У системі REPL у вас немає сценарію. Отже, __dirnameне мав би ніякого реального значення.


5
Також ви не можете використовувати деякі глобальні змінні всередині модулів RequireJS. Якщо ви використовуєте RequireJS на стороні сервера, див. Stackoverflow.com/questions/9027429/… .
— Очі

1
Так, це дійсно слід додати до відповіді Око, бо саме це мене і отримало.
— Томаш Зато - Відновити Моніку

3
Не додаючи, що в сценарій завантаження REPL є нечесним. Я не можу придумати жодних причин, щоб його там не було ...
— jcollum

Я завантажив файл сценарію під час використання REPL за допомогою .load script.js. Це дуже погано __dirname досі недоступний у script.js
— Кевін Вілер

прихильне! врятував мене 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ви можете визначити це як частину сценарію завантаження; це витончено
— jcollum

1
або __dirname = process.cwd()або __dirname=fs.realpathSync('.')або__dirname = process.env.PWD
— Jthorpe

1
path.dirnameначебто більше не приймає нестрокові значення в новітній основній версії 6.0.0, тому перша пропозиція у цій відповіді не спрацює.
— трис

30

У ES6 використовувати:

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

також доступний, коли з вузлом викликається --experimental-modules


Вам не потрібно імпортувати основні модулі в REPL; це завантажить їх на льоту для вас.
— c24w

Це дає поточний робочий каталог, а не каталог поточного .jsфайлу.
— Дірбайо

@Dirbaio, яким би був поточний .jsфайл, коли ти знаходишся у відповіді?
— c24w

@ c24w щойно перевірили, здається, це дає CWD
— Dirbaio

@Dirbaio Я думаю, що це було моєю суттю. Коли ви входите у відповідь, поточного файлу JS немає. Яким би ви хотіли __dirnameбути, якби не CWD?
— c24w

8

Як сказав @qiao, ви не можете використовувати __dirnameу відтворенні вузла. Однак якщо вам знадобиться це значення в консолі, ви можете використовувати 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 та все інше. Жодне стандартне рішення не працювало в моєму випадку. Ось мій проект, який запускає процес як SYSTEM з планувальника завдань, якщо вам нудно github.com/DVLP/Unscheduler. Будь-яке стандартне рішення, яке інакше працює, явно краще, ніж мій злом :)
— Pawel

1

Хоча це не є вирішенням цієї проблеми, я хотів би додати її, оскільки це може допомогти іншим.

Перед dirname має бути два підкреслення , не одна підкреслення ( __dirnameне _dirname).

Документи NodeJS


__ім'я (з двома підкресленнями) не працює у відповіді
— Aaron J Spetner

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", тому ми стикаємося з посиланням error.correct синтаксис - consol.log (__ dirname);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.