nút __dirname không được xác định


137

Từ hướng dẫn nút tôi thấy rằng tôi có thể lấy thư mục của một tệp __dirname, nhưng từ REPL, điều này dường như không được xác định. Đây là một sự hiểu lầm về phía tôi hay lỗi ở đâu?

$ 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
Tôi gặp vấn đề này khi sử dụng eslint, tôi đã đặt nhầm "browser": truethay vì "node": truetrong tệp .eslintrc.json của mình.
Toivo Säwén

Câu trả lời:


186

__dirnamechỉ được định nghĩa trong các tập lệnh. Nó không có sẵn trong REPL.

thử làm một kịch bản a.js

console.log(__dirname);

và chạy nó:

node a.js

bạn sẽ thấy __dirnamein.

Đã thêm giải thích nền: __dirnamecó nghĩa là 'Thư mục của tập lệnh này'. Trong REPL, bạn không có tập lệnh. Do đó, __dirnamesẽ không có bất kỳ ý nghĩa thực sự.


5
Ngoài ra, bạn không thể sử dụng một số biến toàn cầu trong các mô-đun RequireJS. Nếu bạn sử dụng RequireJS ở phía máy chủ, hãy xem stackoverflow.com/questions/9027429/iêu .
Mắt

1
Vâng, điều đó thực sự nên được thêm vào câu trả lời Mắt, bởi vì đó là những gì đã cho tôi.
Tomáš Zato - Phục hồi Monica

3
Không thêm rằng vào tập lệnh tải của REPL là đáng ghét. Tôi không thể nghĩ ra bất kỳ lý do nào nó sẽ không ở đó ...
jcollum

Tôi đã tải một tập tin script trong khi sử dụng REPL .load script.js. Thật tệ khi __dirname vẫn không khả dụng trong script.js
Kevin Wheeler

nâng cao tinh thần! đã cứu tôi 15 phút khi tôi tự hỏi wtf đang diễn ra
PirateApp

96

Dựa trên các câu trả lời hiện có ở đây, bạn có thể xác định điều này trong REPL của mình:

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

Hoặc là:

__dirname = path.resolve();

Nếu không có pathphân đoạn nào được thông qua, path.resolve()sẽ trả về đường dẫn tuyệt đối của thư mục làm việc hiện tại.


Hoặc các lựa chọn thay thế của @ Jthorpe:

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

nếu bạn sử dụng, neshbạn có thể định nghĩa đây là một phần của tập lệnh tải; thật tiện lợi
jcollum

1
hay __dirname = process.cwd()hay __dirname=fs.realpathSync('.')hay__dirname = process.env.PWD
Jthorpe

1
path.dirnamedường như không chấp nhận các giá trị không phải là chuỗi nữa trong phiên bản chính mới nhất 6.0.0, vì vậy đề xuất đầu tiên trong câu trả lời này sẽ không hoạt động.
phân chia

30

Trong ES6 sử dụng:

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

cũng có sẵn khi nút được gọi với --experimental-modules


Bạn không cần nhập các mô-đun lõi trong REPL; nó sẽ tải chúng trên bay cho bạn.
c24w

Điều này cung cấp cho thư mục làm việc hiện tại, không phải thư mục của .jstập tin hiện tại .
Dirbaio

@Dirbaio, tập tin hiện tại.js sẽ là gì khi bạn ở REPL?
c24w

@ c24w vừa mới kiểm tra, có vẻ như sẽ cung cấp cho CWD
Dirbaio

@Dirbaio Tôi nghĩ đó là quan điểm của tôi. Khi bạn nhập REPL, không có tệp JS hiện tại. Bạn muốn __dirnametrở thành gì, nếu không phải là CWD?
c24w

8

Như @ Kiều đã nói, bạn không thể sử dụng __dirnametrong nút thay thế. Tuy nhiên, nếu bạn cần giá trị này trong bảng điều khiển, bạn có thể sử dụng path.resolve()hoặc path.dirname(). Mặc dù, path.dirname()sẽ chỉ cung cấp cho bạn một "." vì vậy, có lẽ không hữu ích Hãy chắc chắn require('path').


3

Có vẻ như bạn cũng có thể làm điều này:

__dirname=fs.realpathSync('.');

tất nhiên, đừng quên fs=require('fs')

(nó không thực sự toàn cầu trong các tập lệnh nút chính xác, nó chỉ được xác định ở cấp độ mô-đun)


Bạn không cần phải yêu cầu các mô-đun cốt lõi trong REPL; nó sẽ tải chúng trên bay cho bạn.
c24w

2

Tôi đã chạy một tập lệnh từ tệp bó với tư cách là người dùng HỆ THỐNG và tất cả các biến như thế process.cwd(), path.resolve()và tất cả các phương thức khác sẽ đưa tôi đường dẫn đến thư mục C: \ Windows \ System32 thay vì đường dẫn thực tế. Trong các thử nghiệm tôi nhận thấy rằng khi một lỗi được ném, ngăn xếp chứa một đường dẫn đúng đến tệp nút.

Đây là một cách rất hay để có được đường dẫn thực sự bằng cách kích hoạt một lỗi và trích xuất đường dẫn từ e.stack. Không được dùng.

// 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;
  }
}

Sử dụng

const dir = veryHackyGetFolder();

Nếu bạn không chạy nó thông qua REPL, bạn có thể sử dụng __dirname__filename.
c24w

Đây là câu trả lời duy nhất mà ít nhất là cố gắng cung cấp giải pháp chính xác.
Tomáš Zato - Phục hồi

@ c24w Tôi đã thử __dirname, __filename và mọi thứ khác. Không có giải pháp tiêu chuẩn làm việc trong trường hợp của tôi. Đây là dự án của tôi chạy một quy trình như HỆ THỐNG từ trình lập lịch tác vụ nếu bạn chán github.com/DVLP/Unscheduler. Bất kỳ giải pháp tiêu chuẩn nào hoạt động khác rõ ràng là tốt hơn so với bản hack của tôi ở trên :)
Pawel

2

Tôi cũng đã cố gắng tham gia vào con đường của mình bằng cách sử dụng path.join(__dirname, 'access.log')nhưng nó đã bị lỗi tương tự.

Đây là cách tôi sửa nó:

Đầu tiên tôi nhập gói đường dẫn và khai báo một biến có tên __dirname, sau đó gọi phương thức resolve đường dẫn .

Trong CommonJS

var path = require("path");

var __dirname = path.resolve();

Trong ES6 +

import path  from 'path';

const __dirname = path.resolve();

Chúc mừng mã hóa .......


1

Mặc dù nó không phải là giải pháp cho vấn đề này, tôi muốn thêm nó vì nó có thể giúp đỡ người khác.

Bạn nên có hai dấu gạch dưới trước dirname, không phải một dấu gạch dưới ( __dirnamekhông _dirname).

Tài liệu NodeJS


__dirname (có hai dấu gạch dưới) không hoạt động trong REPL
Aaron J Spetner

1

Nếu bạn đã node __dirname not definednode --experimental-modules, bạn có thể làm:

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

Vì ví dụ này, chỉ hoạt động với thư mục current / pwd chứ không phải thư mục khác.


1

Nếu bạn đang sử dụng module Node.js , __dirname__filenamekhông tồn tại.

Từ tài liệu Node.js :

Không yêu cầu, xuất, module.exports, __filename, __dirname

Các biến CommonJS này không có sẵn trong các mô-đun ES.

requirecó thể được nhập vào một mô-đun ES bằng cách sử dụng module.createRequire().

Tương đương __filename__dirnamecó thể được tạo bên trong mỗi tệp thông qua 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_Vquire_exports_module_exports_filename_dirname


0

đôi khi chúng tôi tạo một tệp có đuôi .js và thêm consol.log (_dirname); nhưng chúng tôi gặp phải lỗi, chúng tôi rất vội, vì vậy chúng tôi quên thêm một dấu gạch dưới trước "dirname" để chúng tôi đối mặt với lỗi tham chiếu. Cú pháp đúng là consol.log (__ dirname);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.