Determinar o diretório de trabalho da linha de comandos ao executar o script bin do nó

120

Estou criando uma interface de linha de comando do nó. Ele é instalado globalmente e usa um arquivo bin para executar.

Eu pretendo abrir uma janela de comando no diretório raiz dos arquivos nos quais estou trabalhando e, em seguida, basta executar o comando, mas não consegui determinar o diretório de trabalho atual, pois process.cwd()está retornando o diretório do pacote do nó. Inicialmente, assumi que, como o código está sendo executado usando um arquivo em lotes como invólucro (é assim que os arquivos bin podem ser executados sem o nó no início), é impossível, mas o script de café consegue fazê-lo. Dei uma olhada na fonte do roteiro do café, mas não consegui segui-la (sem experiência suficiente).

Para testá-lo, crie um pacote com este arquivo package.json:

{
  "name": "test-package",
  "version": "1.0.0",
  "bin": {
    "test-package":  "./bin/test-package"
  },
  "main": "/lib/test"
}

este arquivo de pacote de teste na lixeira:

#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

Alguém poderia lançar alguma luz sobre isso.

e tente obter o diretório da linha de comandos dentro da lib / test.

Daniel Chatfield
fonte

Respostas:

196
  • process.cwd() retorna o diretório em que o comando foi executado (não o diretório do pacote do nó) se não tiver sido alterado por 'process.chdir' dentro do aplicativo.
  • __filename retorna o caminho absoluto para o arquivo onde está colocado.
  • __dirnameretorna o caminho absoluto para o diretório de __filename.

Se você precisar carregar arquivos do diretório do módulo, precisará usar caminhos relativos.

require('../lib/test');

ao invés de

var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

É sempre relativo ao arquivo de onde ele chamou e não depende do diretório de trabalho atual.

Vadim Baryshev
fonte
2
Depois process.chdir(), existe alguma maneira de obter o original?
reergymerej
@reergymerej Provavelmente, você desejará armazenar o cwd antes de executar chdir () (por exemplo, var originalCwd = process.cwd();execute o seu process.chdir()e poderá retornar ao original posteriormente).
Swivel
é ../lib/testportátil?
26617 Sebastian
Não. Não é uma solução portátil porque o Windows usa barras invertidas. Portanto, se você tentar executá-lo no Windows, não funcionará.
zachdyer
1
Na verdade, para o NodeJS, tudo é igual. Mesmo no Windows, você pode exigir convenientemente caminhos relativos da maneira Unix. Então, ../lib/testé portátil, enquanto a contrapartida do Windows ..\lib\testnão é ...
Christian Ulbrich
48

Diretório de trabalho atual

Para obter o diretório de trabalho atual, você pode usar:

process.cwd()

No entanto, esteja ciente de que alguns scripts, principalmente o gulp, mudarão o diretório de trabalho atual com process.chdir().

Caminho do módulo do nó

Você pode obter o caminho do módulo atual com:

  • __filename
  • __dirname

Diretório original (onde o comando foi iniciado)

Se você estiver executando um script na linha de comando e desejar o diretório original a partir do qual o script foi executado, independentemente do diretório em que o script está operando atualmente, você poderá usar:

process.env.INIT_CWD

Diretório original, ao trabalhar com scripts NPM

Às vezes, é desejável executar um script NPM no diretório atual, em vez da raiz do projeto.

Essa variável está disponível dentro dos scripts do pacote npm como:

$INIT_CWD.

Você deve estar executando uma versão recente do NPM. Se essa variável não estiver disponível, verifique se o NPM está atualizado.

Isso permitirá que você acesse o caminho atual em seu package.json, por exemplo:

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
superluminário
fonte
process.env.INIT_CWDretorna o dir depackage.json
vaughan
2
Cuidado, $ INIT_CWD só funciona no Linux. Para Windows, você terá que usar% INIT_CWD%. Eu acho que esse problema pode ser superado usando o npmjs.com/package/cross-env , mas eu ainda não tentei isso #
Stephanie
3

Como alternativa, se você deseja obter apenas o diretório atual do script atual do NodeJS, tente algo simples como este. Observe que isso não funcionará na própria CLI do nó:

var fs = require('fs'),
    path = require('path');

var dirString = path.dirname(fs.realpathSync(__filename));

// output example: "/Users/jb/workspace/abtest"
console.log('directory to start walking...', dirString);
John Paul Barbagallo
fonte
3

path.resolve('.')também é uma opção confiável e limpa, porque quase sempre require('path'). Ele fornecerá o caminho absoluto do diretório de onde é chamado.

sziraqui
fonte
0

Aqui está o que funcionou para mim:

console.log(process.mainModule.filename);
Etienne Martin
fonte