Come posso ottenere il percorso dello script corrente con Node.js?


980

Come posso ottenere il percorso dello script in Node.js?

So che c'è process.cwd, ma ciò si riferisce solo alla directory in cui è stato chiamato lo script, non allo script stesso. Ad esempio, dire che sono dentro /home/kyle/ed eseguo il comando seguente:

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

Se chiamo process.cwd(), ricevo /home/kyle/, no /home/kyle/some/dir/. C'è un modo per ottenere quella directory?


6
nodejs.org/docs/latest/api/globals.html il collegamento di documentazione della risposta accettata.
Allenhwkim,

Risposte:


1395

L'ho trovato dopo aver consultato di nuovo la documentazione. Quello che cercavo era la __filenamee __dirnamevariabili a livello di modulo.

  • __filenameè il nome del file del modulo corrente. Questo è il percorso assoluto risolto del file del modulo corrente. (es: /home/kyle/some/dir/file.js)
  • __dirnameè il nome della directory del modulo corrente. (es: /home/kyle/some/dir)

3
Se si desidera solo il nome della directory e non il percorso completo, è possibile fare qualcosa del genere: function getCurrentDirectoryName () {var fullPath = __dirname; var path = fullPath.split ('/'); var cwd = path [path.length-1]; return cwd; }
Anthony Martin,

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

6
Per coloro che provano la soluzione @apx (come ho fatto :), questa soluzione non funziona su Windows.
Laoujin,

36
O semplicemente__dirname.split(path.sep).pop()
Burgi,

47
Oppurerequire('path').basename(__dirname);
Vyacheslav Cotruta il

251

Quindi in pratica puoi farlo:

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

Usa resol () invece di concatenare con '/' o '\' altrimenti incontrerai problemi multipiattaforma.

Nota: __dirname è il percorso locale del modulo o dello script incluso. Se stai scrivendo un plugin che deve conoscere il percorso dello script principale è:

require.main.filename

oppure, per ottenere solo il nome della cartella:

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

16
Se il tuo obiettivo è solo quello di analizzare e interagire con il file json, spesso puoi farlo più facilmente tramite var settings = require('./settings.json'). Naturalmente, è sincrono per IO, quindi non farlo in fase di esecuzione, ma al momento dell'avvio va bene e una volta caricato, verrà memorizzato nella cache.
isaacs

2
@Marc Grazie! Da un po 'di tempo mi sono fatto strada tra il fatto che __dirname è locale per ogni modulo. Ho una struttura nidificata nella mia libreria e devo conoscere in diversi punti la radice della mia app. Sono contento di saperlo ora: D
Thijs Koerselman,

Nodo V8: path.dirname (process.mainModule.filename)
wayofthefuture,

Se non consideri Windows una vera piattaforma, possiamo saltare la risoluzione? BSD, Macos, Linux, Tizen, Symbian, Solaris, Android, Flutter, Webos tutti usano / giusto?
Ray Foss,


119

Questo comando restituisce la directory corrente:

var currentPath = process.cwd();

Ad esempio, per utilizzare il percorso per leggere il file:

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

Per coloro che non capivano asincrona e sincrona , si veda questo link ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
questo è esattamente ciò che l'OP non vuole ... la richiesta è per il percorso dello script eseguibile!
Cesare

3
La directory corrente è una cosa molto diversa. Se si esegue qualcosa del genere cd /foo; node bar/test.js, la directory corrente sarebbe /foo, ma lo script si trova in /foo/bar/test.js.
rjmunro,

Non è una buona risposta. È un casino logico portoghese, questo può essere un percorso molto più breve di quanto ti aspetti.
kris_IV

Perché mai dovresti farlo? se il file fosse relativo alla directory corrente che potresti leggere text.txte funzionerebbe, non è necessario costruire il percorso assoluto
Michael Mrozek,

104

Usa __dirname !!

__dirname

Il nome della directory del modulo corrente. Questo è lo stesso del path.dirname () di __filename.

Esempio: esecuzione del nodo example.js da / Users / mjr

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

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

Per i moduli ESM vorresti usare: import.meta.url


1
Questo sopravvive anche ai collegamenti simbolici. Quindi se crei un cestino e hai bisogno di trovare un file, ad esempio path.join (__ dirname, "../example.json"); funzionerà ancora quando il tuo binario è collegato in node_modules / .bin
Jason

2
Non solo questa risposta è stata data anni prima, ma non funziona più con i moduli ES .
Dan Dascalescu,

48

Quando si tratta dello script principale è semplice come:

process.argv[1]

Dalla documentazione di Node.js :

process.argv

Un array contenente gli argomenti della riga di comando. Il primo elemento sarà 'nodo', il secondo elemento sarà il percorso del file JavaScript . I prossimi elementi saranno eventuali argomenti della riga di comando aggiuntivi.

Se è necessario conoscere il percorso di un file del modulo, utilizzare __filename .


3
Il downvoter potrebbe spiegare perché questo non è raccomandato?
Tamlyn,

1
@Tamlyn Forse perché si process.argv[1]applica solo allo script principale mentre __filenamepunta al file del modulo in esecuzione. Aggiornamento la mia risposta per sottolineare la differenza. Tuttavia, non vedo nulla di male nell'uso process.argv[1]. Dipende dalle proprie esigenze.
Lukasz Wiktor,

10
Se lo script principale è stato avviato con un gestore processi nodo come pm2 process.argv [1] punterà all'eseguibile del gestore processi /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

Node.js 10 supporta i moduli ECMAScript , dove __dirnamee __filenamenon sono più disponibili .

Quindi per ottenere il percorso del modulo ES corrente è necessario utilizzare:

import { fileURLToPath } from 'url';

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

E per la directory che contiene il modulo corrente:

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

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

Come faccio a sapere se sto scrivendo un modulo ES o no? Dipende solo dalla versione del nodo in uso o se utilizzo parole chiave di importazione / esportazione?
Ed Brannin,

2
Moduli ES disponibili solo con --experimental-modulesflag.
Nickensoul,

1
--experimental-modules è richiesto solo se si esegue la versione del nodo <13.2. basta nominare il file .mjs anziché .js
Brent,



13

So che questo è piuttosto vecchio, e la domanda originale a cui stavo rispondendo è contrassegnata come duplicata e diretta qui, ma ho riscontrato un problema nel tentativo di far funzionare i giornalisti di gelsomini e non mi piaceva l'idea che dovevo effettuare il downgrade per farlo funzionare. Ho scoperto che jasmine-reporter non stava risolvendo correttamente savePath e stava effettivamente inserendo l'output della cartella dei report nella directory jasmine-reporter anziché nella directory principale in cui ho eseguito gulp. Per farlo funzionare correttamente ho finito con process.env.INIT_CWD per ottenere la directory di lavoro corrente iniziale che dovrebbe essere la directory in cui hai eseguito gulp. Spero che questo aiuti qualcuno.

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

8

È possibile utilizzare process.env.PWD per ottenere il percorso della cartella dell'app corrente.


2
OP richiede il "percorso dello script" richiesto. PWD, che sta per qualcosa come Process Working Directory, non è questo. Inoltre, il fraseggio "app corrente" è fuorviante.
dmcontador,

7

Se stai usando pkgper impacchettare la tua app, troverai utile questa espressione:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkgindica se l'app è stata impacchettata da pkg.

  • process.execPathcontiene il percorso completo dell'eseguibile, che è /usr/bin/nodeo simile per invocazioni dirette di script ( node test.js) o dell'app in pacchetto.

  • require.main.filename contiene l'intero percorso dello script principale, ma è vuoto quando Node viene eseguito in modalità interattiva.

  • __dirnamecontiene l'intero percorso dello script corrente , quindi non lo sto usando (anche se potrebbe essere quello che OP richiede; quindi meglio usare appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));notando che in modalità interattiva __dirnameè vuoto.

  • Per la modalità interattiva, utilizzare process.argv[0]per ottenere il percorso dell'eseguibile Nodo o process.cwd()per ottenere la directory corrente.


3

Utilizzare il basenamemetodo del pathmodulo:

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

Qui la documentazione da cui è tratto l'esempio sopra.

Come ha sottolineato Dan, Node sta lavorando su moduli ECMAScript con il flag "--experimental-modules". Il nodo 12 supporta__dirname__filename ancora e come sopra.


Se stai usando la --experimental-modulesbandiera, c'è un approccio alternativo .

L'alternativa è ottenere il percorso al modulo ES corrente :

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

E per la directory che contiene il modulo corrente:

import path from 'path';

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

-2

Se vuoi qualcosa di più simile a $ 0 in uno script di shell, prova questo:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.