Comment obtenir le chemin d'accès au script actuel avec Node.js?


980

Comment puis-je obtenir le chemin d'accès au script dans Node.js?

Je sais qu'il y en a process.cwd, mais cela ne fait référence qu'au répertoire où le script a été appelé, pas au script lui-même. Par exemple, disons que je suis dedans /home/kyle/et que j'exécute la commande suivante:

node /home/kyle/some/dir/file.js

Si j'appelle process.cwd(), je reçois /home/kyle/, non /home/kyle/some/dir/. Existe-t-il un moyen d'obtenir ce répertoire?


6
nodejs.org/docs/latest/api/globals.html le lien de documentation de la réponse acceptée.
allenhwkim

Réponses:


1395

Je l'ai trouvé après avoir parcouru à nouveau la documentation. Ce que je cherchais, c'était les variables de niveau module __filenameet __dirname.

  • __filenameest le nom de fichier du module actuel. Il s'agit du chemin absolu résolu du fichier de module actuel. (ex: /home/kyle/some/dir/file.js)
  • __dirnameest le nom du répertoire du module actuel. (ex: /home/kyle/some/dir)

3
Si vous ne voulez que le nom du répertoire et non le chemin complet, vous pouvez faire quelque chose comme ceci: function getCurrentDirectoryName () {var fullPath = __dirname; var path = fullPath.split ('/'); var cwd = chemin [chemin.longueur-1]; return cwd; }
Anthony Martin

58
@AnthonyMartin __dirname.split ("/"). Pop ()
19h

6
Pour ceux qui essaient la solution @apx (comme je l'ai fait :), cette solution ne fonctionne pas sous Windows.
Laoujin

36
Ou tout simplement__dirname.split(path.sep).pop()
Burgi

47
Ourequire('path').basename(__dirname);
Vyacheslav Cotruta

251

Donc, fondamentalement, vous pouvez le faire:

fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);

Utilisez resolver () au lieu de concaténer avec '/' ou '\' sinon vous rencontrerez des problèmes multiplates-formes.

Remarque: __dirname est le chemin local du module ou du script inclus. Si vous écrivez un plugin qui a besoin de connaître le chemin du script principal c'est:

require.main.filename

ou, pour obtenir simplement le nom du dossier:

require('path').dirname(require.main.filename)

16
Si votre objectif est simplement d'analyser et d'interagir avec le fichier json, vous pouvez souvent le faire plus facilement via var settings = require('./settings.json'). Bien sûr, il s'agit d'E / S fs synchrones, alors ne le faites pas au moment de l'exécution, mais au moment du démarrage, tout va bien, et une fois qu'il sera chargé, il sera mis en cache.
isaacs

2
@Marc Merci! Depuis un moment maintenant, je me frayais un chemin autour du fait que __dirname est local pour chaque module. J'ai une structure imbriquée dans ma bibliothèque et j'ai besoin de connaître à plusieurs endroits la racine de mon application. Heureux de savoir comment faire maintenant: D
Thijs Koerselman

Node V8: path.dirname (process.mainModule.filename)
wayofthefuture

Si vous ne considérez pas Windows comme une véritable plate-forme, pouvons-nous ignorer la résolution? BSD, Macos, linux, tizen, symbian, Solaris, android, flutter, webos tous utilisent / non?
Ray Foss


119

Cette commande renvoie le répertoire courant:

var currentPath = process.cwd();

Par exemple, pour utiliser le chemin d'accès pour lire le fichier:

var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});

Pour ceux qui ne comprennent pas Asynchrone et Synchrone , consultez ce lien ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
c'est exactement ce que l'OP ne veut pas ... la demande est pour le chemin du script exécutable!
caesarsol

3
Le répertoire actuel est une chose très différente. Si vous exécutez quelque chose comme cd /foo; node bar/test.js, le répertoire courant le serait /foo, mais le script se trouve dans /foo/bar/test.js.
rjmunro

Ce n'est pas une bonne réponse. C'est un bordel logique car cela peut être un chemin beaucoup plus court que ce à quoi vous vous attendez.
kris_IV

Pourquoi voudriez-vous faire cela? si le fichier était relatif au répertoire courant que vous pouviez simplement lire text.txtet que cela fonctionnerait, vous n'avez pas besoin de construire le chemin absolu
Michael Mrozek

104

Utilisez __dirname !!

__dirname

Le nom du répertoire du module actuel. C'est la même chose que le path.dirname () du __filename.

Exemple: exécution de node example.js à partir de / Users / mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

https://nodejs.org/api/modules.html#modules_dirname

Pour les ESModules, vous souhaitez utiliser: import.meta.url


1
Cela survit aussi aux liens symboliques. Donc, si vous créez un bac et que vous devez trouver un fichier, par exemple path.join (__ dirname, "../example.json"); cela fonctionnera quand votre binaire sera lié dans node_modules / .bin
Jason

2
Non seulement cette réponse a été donnée des années plus tôt, mais elle ne fonctionne plus avec les modules ES .
Dan Dascalescu

48

En ce qui concerne le script principal, c'est aussi simple que:

process.argv[1]

Dans la documentation Node.js :

process.argv

Un tableau contenant les arguments de la ligne de commande. Le premier élément sera «nœud», le deuxième élément sera le chemin d'accès au fichier JavaScript . Les éléments suivants seront tous les arguments de ligne de commande supplémentaires.

Si vous avez besoin de connaître le chemin d'un fichier de module, utilisez __filename .


3
Le votant pourrait-il expliquer pourquoi cela n'est pas recommandé?
Tamlyn

1
@Tamlyn Peut-être parce que process.argv[1]s'applique uniquement au script principal alors qu'il __filenamepointe vers le fichier de module en cours d'exécution. Je mets à jour ma réponse pour souligner la différence. Pourtant, je ne vois rien de mal à utiliser process.argv[1]. Dépend de ses besoins.
Lukasz Wiktor

10
Si le script principal a été lancé avec un gestionnaire de processus de nœud tel que pm2 process.argv [1] pointera vers l'exécutable du gestionnaire de processus /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

Node.js 10 prend en charge les modules ECMAScript , où __dirnameet __filenamene sont plus disponibles .

Ensuite, pour obtenir le chemin vers le module ES actuel, il faut utiliser:

import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);

Et pour le répertoire contenant le module courant:

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

Comment savoir si j'écris un module ES ou non? Est-ce juste une question de quelle version de nœud j'utilise, ou si j'utilise des mots-clés d'importation / exportation?
Ed Brannin

2
Modules ES disponibles uniquement avec --experimental-modulesindicateur.
Nickensoul

1
--experimental-modules n'est requis que si vous exécutez la version du nœud <13.2. nommez simplement le fichier .mjs plutôt que .js
Brent


24

Chaque programme Node.js a des variables globales dans son environnement, qui représentent des informations sur votre processus et l'une d'elles __dirname.


Non seulement cette réponse a été donnée des années plus tôt, mais elle __dirname ne fonctionne plus avec les modules ES .
Dan Dascalescu

Il s'agit de NodeJs 10, mais cette réponse a été publiée en 2016.
Hazarapet Tunanyan

Je connais. Les réponses peuvent être mises à jour à mesure que la technologie évolue.
Dan Dascalescu

13

Je sais que c'est assez vieux, et la question d'origine à laquelle je répondais est marquée comme dupliquée et dirigée ici, mais j'ai rencontré un problème en essayant de faire travailler les reporters de jasmin et je n'aimais pas l'idée que je devais rétrograder dans pour qu'il fonctionne. J'ai découvert que jasmine-reporters ne résolvait pas correctement le savePath et mettait en fait la sortie du dossier de rapports dans le répertoire jasmine-reporters au lieu du répertoire racine de l'endroit où j'ai exécuté gulp. Pour que cela fonctionne correctement, j'ai fini par utiliser process.env.INIT_CWD pour obtenir le répertoire de travail actuel initial qui devrait être le répertoire où vous avez exécuté gulp. J'espère que cela aide quelqu'un.

var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
  savePath: process.env.INIT_CWD + '/report/e2e/',
  consolidateAll: true,
  captureStdout: true
 });

8

Vous pouvez utiliser process.env.PWD pour obtenir le chemin du dossier d'application actuel.


2
OP demande le "chemin d'accès au script" demandé. PWD, qui signifie quelque chose comme Process Working Directory, n'est pas cela. En outre, le libellé de "l'application actuelle" est trompeur.
dmcontador

7

Si vous utilisez pkgpour empaqueter votre application, vous trouverez cette expression utile:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkgindique si l'application a été mise en package par pkg.

  • process.execPathcontient le chemin complet de l'exécutable, qui est /usr/bin/nodeou similaire pour les appels directs de scripts ( node test.js), ou de l'application empaquetée.

  • require.main.filename contient le chemin complet du script principal, mais il est vide lorsque Node s'exécute en mode interactif.

  • __dirnamecontient le chemin complet du script actuel , donc je ne l'utilise pas (bien que ce soit peut-être ce que demande OP; alors mieux vaut appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));noter qu'en mode interactif __dirnameest vide.

  • Pour le mode interactif, utilisez soit process.argv[0]pour obtenir le chemin d'accès à l'exécutable Node, soit process.cwd()pour obtenir le répertoire courant.


3

Utilisez la basenameméthode du pathmodule:

var path = require('path');
var filename = path.basename(__filename);
console.log(filename);

Voici la documentation dont l'exemple ci-dessus est tiré.

Comme Dan l'a souligné, Node travaille sur des modules ECMAScript avec l'indicateur "--experimental-modules". Le noeud 12 prend__dirname__filename toujours en charge et comme ci-dessus.


Si vous utilisez le --experimental-modulesdrapeau, il existe une approche alternative .

L'alternative est d'obtenir le chemin vers le module ES actuel :

const __filename = new URL(import.meta.url).pathname;

Et pour le répertoire contenant le module courant:

import path from 'path';

const __dirname = path.dirname(new URL(import.meta.url).pathname);

-2

Si vous voulez quelque chose de plus comme $ 0 dans un script shell, essayez ceci:

var path = require('path');

var command = getCurrentScriptPath();

console.log(`Usage: ${command} <foo> <bar>`);

function getCurrentScriptPath () {
    // Relative path from current working directory to the location of this script
    var pathToScript = path.relative(process.cwd(), __filename);

    // Check if current working dir is the same as the script
    if (process.cwd() === __dirname) {
        // E.g. "./foobar.js"
        return '.' + path.sep + pathToScript;
    } else {
        // E.g. "foo/bar/baz.js"
        return pathToScript;
    }
}

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.