noeud __dirname non défini


138

Dans le manuel du nœud, je vois que je peux obtenir le répertoire d'un fichier avec __dirname, mais à partir du REPL, cela semble être indéfini. Est-ce un malentendu de ma part ou où est l'erreur?

$ 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
J'ai eu ce problème lors de l'utilisation d'eslint, j'avais défini par erreur "browser": trueau lieu de "node": truedans mon fichier .eslintrc.json.
— Toivo Säwén

Réponses:


187

__dirnamen'est défini que dans les scripts. Il n'est pas disponible dans REPL.

essayez de créer un script a.js

console.log(__dirname);

et exécutez-le:

node a.js

vous verrez __dirnameimprimé.

Explication en arrière-plan ajoutée: __dirnamesignifie «Le répertoire de ce script». Dans REPL, vous n'avez pas de script. Par conséquent, __dirnamen'aurait aucune signification réelle.


5
De plus, vous ne pouvez pas utiliser certaines des variables globales dans les modules RequireJS. Si vous utilisez RequireJS côté serveur, consultez stackoverflow.com/questions/9027429/… .
— Eye

1
Ouais, cela devrait vraiment être ajouté à la réponse Eye, car c'est ce qui m'a attiré.
— Tomáš Zato - Réintégrer Monica

3
Ne pas ajouter cela au script de chargement du REPL est odieux. Je ne vois aucune raison pour laquelle il ne serait pas là ...
— jcollum

J'ai chargé un fichier de script à l'intérieur du REPL en utilisant .load script.js. C'est dommage que __dirname ne soit toujours pas disponible à partir de script.js
— Kevin Wheeler

voté! m'a sauvé 15 minutes alors que je me demandais que wtf se passe
— PirateApp

96

En vous basant sur les réponses existantes ici, vous pouvez définir ceci dans votre REPL:

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

Ou:

__dirname = path.resolve();

Si aucun pathsegment n'est passé, path.resolve()renvoie le chemin absolu du répertoire de travail actuel.


Ou les alternatives de @ Jthorpe:

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

si vous utilisez, neshvous pouvez le définir dans le cadre de votre script de chargement;
— It

1
ou __dirname = process.cwd()ou __dirname=fs.realpathSync('.')ou__dirname = process.env.PWD
— Jthorpe

1
path.dirnamesemble ne plus accepter les valeurs non-chaîne dans la dernière version majeure 6.0.0, donc la première suggestion de cette réponse ne fonctionnera pas.
— trysis le

30

Dans ES6, utilisez:

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

également disponible lorsque le nœud est appelé avec --experimental-modules


Vous n'avez pas besoin d'importer les modules de base dans le REPL; il les chargera à la volée pour vous.
— c24w

Cela donne le répertoire de travail actuel, pas le répertoire du .jsfichier courant .
— Dirbaio

@Dirbaio, quel serait le fichier actuel.js lorsque vous êtes dans la REPL?
— c24w le

@ c24w vient de vérifier, il semble donner le CWD
— Dirbaio le

@Dirbaio Je pense que c'était mon argument. Lorsque vous entrez le REPL, il n'y a pas de fichier JS en cours. Que voudriez-vous __dirnameêtre, sinon le CWD?
— c24w

8

Comme @qiao l'a dit, vous ne pouvez pas utiliser __dirnamedans le nœud repl. Cependant, si vous avez besoin de cette valeur dans la console, vous pouvez utiliser path.resolve()ou path.dirname(). Bien que, path.dirname()vous donnera juste un "." donc, probablement pas si utile. Soyez sûr de require('path').


3

Il semble que vous puissiez également faire ceci:

__dirname=fs.realpathSync('.');

bien sûr, n'oubliez pas fs=require('fs')

(ce n'est pas vraiment global dans les scripts de nœuds exactement, c'est juste défini au niveau du module)


Vous n'avez pas besoin d'exiger des modules de base dans le REPL; il les chargera à la volée pour vous.
— c24w

3

J'essayais également de rejoindre mon chemin en utilisant path.join(__dirname, 'access.log')mais cela lançait la même erreur.

Voici comment je l'ai résolu:

J'ai d'abord importé le package path et déclaré une variable nommée __dirname, puis appelé la méthode resolve path .

En communJS

var path = require("path");

var __dirname = path.resolve();

Dans ES6 +

import path  from 'path';

const __dirname = path.resolve();

Bon codage .......


2

J'exécutais un script à partir d'un fichier de commandes en tant qu'utilisateur SYSTEM et toutes les variables comme process.cwd(), path.resolve()et toutes les autres méthodes me donnaient le chemin vers le dossier C: \ Windows \ System32 au lieu du chemin réel. Au cours des expériences, j'ai remarqué que lorsqu'une erreur est lancée, la pile contient un vrai chemin vers le fichier de nœud.

Voici un moyen très piraté d'obtenir le vrai chemin en déclenchant une erreur et en extrayant le chemin de e.stack. Ne pas utiliser.

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

Usage

const dir = veryHackyGetFolder();

Si vous ne l'exécutez pas via le REPL, vous pouvez utiliser __dirnameet __filename.
— c24w

C'est la seule réponse qui tente au moins de fournir une solution correcte.
— Tomáš Zato - Réintégrer Monica le

@ c24w J'ai essayé __dirname, __filename et tout le reste. Aucune solution standard n'a fonctionné dans mon cas. Voici mon projet qui exécute un processus en tant que SYSTEM à partir du planificateur de tâches si vous vous ennuyez github.com/DVLP/Unscheduler. Toute solution standard qui fonctionne autrement est évidemment meilleure que mon hack ci-dessus :)
— Pawel

1

Bien que ce ne soit pas la solution à ce problème, je voudrais l'ajouter car cela peut aider les autres.

Vous devriez avoir deux traits de soulignement avant dirname, pas un trait de soulignement ( __dirnamepas _dirname).

Documents NodeJS


__dirname (avec deux traits de soulignement) ne fonctionne pas dans la REPL
— Aaron J Spetner

1

Si vous avez node __dirname not definedavec node --experimental-modules, vous pouvez faire:

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

Parce qu'autre exemple, ne fonctionne qu'avec le répertoire actuel / pwd et non avec un autre répertoire.


1

Si vous utilisez des modules Node.js , __dirnameet __filenamen'existez pas.

À partir de la documentation Node.js :

Pas d'exigences, exportations, module.exports, __filename, __dirname

Ces variables CommonJS ne sont pas disponibles dans les modules ES.

requirepeut être importé dans un module ES à l'aide de module.createRequire().

Des équivalents de __filenameet __dirnamepeuvent être créés à l'intérieur de chaque fichier via 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

parfois nous créons un fichier avec l'extension .js et ajoutons consol.log (_dirname); mais nous sommes confrontés à des erreurs, nous sommes pressés, nous oublions donc d'ajouter un autre trait de soulignement avant le "dirname" afin que nous soyons confrontés à l'erreur de référence. La syntaxe correcte est consol.log (__ dirname);

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.