Como obtenho o caminho para o script atual com o Node.js?


979

Como obteria o caminho para o script no Node.js?

Eu sei que há process.cwd, mas isso se refere apenas ao diretório em que o script foi chamado, não ao próprio script. Por exemplo, diga que eu estou /home/kyle/e corro o seguinte comando:

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

Se eu ligar process.cwd(), eu entendo /home/kyle/, não /home/kyle/some/dir/. Existe uma maneira de obter esse diretório?


6
nodejs.org/docs/latest/api/globals.html o link da documentação da resposta aceita.
allenhwkim

Respostas:


1393

Encontrei depois de examinar a documentação novamente. O que eu estava procurando eram o __filenamee __dirnamevariáveis de nível de módulo.

  • __filenameé o nome do arquivo do módulo atual. Este é o caminho absoluto resolvido do arquivo de módulo atual. (ex: /home/kyle/some/dir/file.js)
  • __dirnameé o nome do diretório do módulo atual. (ex: /home/kyle/some/dir)

3
Se você deseja apenas o nome do diretório e não o caminho completo, faça algo assim: function getCurrentDirectoryName () {var fullPath = __dirname; caminho var = fullPath.split ('/'); var cwd = caminho [path.length-1]; retornar cwd; }
Anthony Martin

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

6
Para aqueles que tentam a solução @apx (como eu fiz :), essa solução não funciona no Windows.
Laoujin

36
Ou simplesmente__dirname.split(path.sep).pop()
Burgi

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

251

Então, basicamente, você pode fazer isso:

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

Use resolve () em vez de concatenar com '/' ou '\', caso contrário, você terá problemas entre plataformas.

Nota: __dirname é o caminho local do módulo ou script incluído. Se você está escrevendo um plugin que precisa conhecer o caminho do script principal, é:

require.main.filename

ou, para obter apenas o nome da pasta:

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

16
Se seu objetivo é apenas analisar e interagir com o arquivo json, é possível fazer isso com mais facilidade por meio de var settings = require('./settings.json'). Obviamente, é IO síncrona do fs, portanto, não faça isso em tempo de execução, mas no momento da inicialização está bom e, uma vez carregado, será armazenado em cache.
Isaacs

2
@ Marc Thanks! Por um tempo, agora eu estava tentando entender o fato de que __dirname é local para cada módulo. Eu tenho uma estrutura aninhada na minha biblioteca e preciso conhecer em vários lugares a raiz do meu aplicativo. Ainda bem que eu sei como fazer isso agora: D
Thijs Koerselman

Nó V8: path.dirname (process.mainModule.filename)
wayofthefuture

Se você não considera o Windows uma plataforma real, podemos pular a resolução? BSD, Macos, linux, tizen, symbian, Solaris, andróide, vibração, webos todos usam / certo?
Ray Foss


119

Este comando retorna o diretório atual:

var currentPath = process.cwd();

Por exemplo, para usar o caminho para ler o arquivo:

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

Para aqueles que não entendia assíncrona e síncrona , consulte este link ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
é exatamente isso que o OP não deseja ... a solicitação é para o caminho do script executável!
caesarsol

3
O diretório atual é uma coisa muito diferente. Se você executar algo como cd /foo; node bar/test.js, o diretório atual seria /foo, mas o script está localizado em /foo/bar/test.js.
Rjmunro 5/07

Não é uma boa resposta. É uma bagunça uma lógica, pois esse pode ser um caminho muito mais curto do que o esperado.
kris_IV

Por que você faria isso; se o arquivo fosse relativo ao diretório atual, você pode apenas ler text.txte ele iria trabalhar, você não precisa para construir o caminho absoluto
Michael Mrozek

104

Use __dirname !!

__dirname

O nome do diretório do módulo atual. É o mesmo que o path.dirname () do __filename.

Exemplo: executando o nó example.js 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

Para ESModules, você desejaria usar: import.meta.url


1
Isso também sobrevive aos links simbólicos. Portanto, se você criar uma lixeira e precisar encontrar um arquivo, por exemplo, path.join (__ dirname, "../example.json"); ele ainda funciona quando o binário é ligado em node_modules / bin
Jason

2
Essa resposta não só foi dada anos antes, mas também não funciona mais com os módulos ES .
Dan Dascalescu

48

Quando se trata do script principal, é tão simples quanto:

process.argv[1]

A partir da documentação Node.js :

process.argv

Uma matriz contendo os argumentos da linha de comando. O primeiro elemento será 'node', o segundo elemento será o caminho para o arquivo JavaScript . Os próximos elementos serão quaisquer argumentos adicionais da linha de comando.

Se você precisar conhecer o caminho de um arquivo de módulo, use __filename .


3
O downvoter poderia explicar por que isso não é recomendado?
Tamlyn

1
@Tamlyn Talvez porque process.argv[1]se aplique apenas ao script principal enquanto __filenameaponta para o arquivo do módulo que está sendo executado. Eu atualizo minha resposta para enfatizar a diferença. Ainda assim, não vejo nada de errado em usar process.argv[1]. Depende dos requisitos.
Lukasz Wiktor

10
Se o script principal foi iniciado com um gerenciador de processos de nó, como pm2 process.argv [1], apontará para o executável do gerenciador de processos /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

O Node.js 10 suporta módulos ECMAScript , onde __dirnamee __filenamenão estão mais disponíveis .

Então, para obter o caminho para o módulo ES atual, é necessário usar:

import { fileURLToPath } from 'url';

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

E para o diretório que contém o módulo atual:

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

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

Como saber se estou escrevendo um módulo ES ou não? É apenas uma questão de qual versão do Nó estou executando ou se estou usando palavras-chave de importação / exportação?
Ed Ednnin 18/04/19

2
Módulos ES disponíveis apenas com --experimental-modulessinalizador.
Nickensoul

1
--experimental-modules será necessário apenas se você estiver executando a versão do nó <13.2. apenas nomeie o arquivo .mjs em vez de .js
Brent



13

Sei que isso é bastante antigo, e a pergunta original à qual eu estava respondendo está marcada como duplicada e direcionada aqui, mas encontrei um problema ao tentar fazer com que os repórteres de jasmim funcionassem e não gostei da ideia de ter que fazer o downgrade ordem para que ele funcione. Descobri que o jasmine-repórteres não estava resolvendo o savePath corretamente e, na verdade, estava colocando a saída da pasta de relatórios no diretório jasmine-repórteres, em vez do diretório raiz do local onde executei o gulp. Para fazer isso funcionar corretamente, acabei usando process.env.INIT_CWD para obter o Diretório de trabalho atual inicial, que deve ser o diretório em que você executou o gulp. Espero que isso ajude alguém.

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

8

Você pode usar process.env.PWD para obter o caminho atual da pasta do aplicativo.


2
O OP solicita o "caminho para o script" solicitado. PWD, que significa algo como Process Working Directory, não é isso. Além disso, a expressão "aplicativo atual" é enganosa.
dmcontador 8/09/17

7

Se você estiver usando pkgpara empacotar seu aplicativo, achará útil esta expressão:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkginforma se o aplicativo foi compactado por pkg.

  • process.execPathmantém o caminho completo do executável, que é /usr/bin/nodeou semelhante para invocações diretas de scripts ( node test.js) ou do aplicativo empacotado.

  • require.main.filename mantém o caminho completo do script principal, mas fica vazio quando o Node é executado no modo interativo.

  • __dirnamecontém o caminho completo do script atual , então não o estou usando (embora possa ser o que o OP pede; então é melhor usar appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));observando que no modo interativo __dirnameestá vazio.

  • Para o modo interativo, use process.argv[0]para obter o caminho para o executável do Nó ou process.cwd()para obter o diretório atual.


3

Use o basenamemétodo do pathmódulo:

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

Aqui está a documentação da qual o exemplo acima foi retirado.

Como Dan apontou, o Node está trabalhando nos módulos ECMAScript com o sinalizador "--experimental-modules". O nó 12 ainda suporta __dirnamee__filename como acima.


Se você estiver usando a --experimental-modulesbandeira, existe uma abordagem alternativa .

A alternativa é obter o caminho para o módulo ES atual :

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

E para o diretório que contém o módulo atual:

import path from 'path';

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

-2

Se você quiser algo mais como $ 0 em um script de shell, tente o seguinte:

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.