Определить рабочий каталог командной строки при запуске скрипта bin узла

121

Я создаю интерфейс командной строки узла. Он устанавливается глобально и для выполнения использует файл bin.

Я планирую открыть командное окно в корневом каталоге файлов, над которыми я работаю, а затем просто запустить команду, однако мне не удалось определить текущий рабочий каталог, поскольку process.cwd()он возвращает каталог пакета узла. Я изначально предполагал, что, поскольку код выполняется с использованием пакетного файла в качестве оболочки (именно так файлы bin могут выполняться без узла в начале), это невозможно, но coffee-script справляется с этим. Я взглянул на исходник кофейного сценария, но не смог его уследить (недостаточно опытный).

Чтобы проверить это на себе, создайте пакет с этим файлом package.json:

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

этот файл тестового пакета в bin:

#!/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');

Может ли кто-нибудь пролить свет на это.

а затем попробуйте получить каталог командной строки внутри lib / test.

Дэниел Чатфилд
источник

Ответы:

196
  • process.cwd() возвращает каталог, в котором была выполнена команда (не каталог пакета узла), если он не был изменен с помощью 'process.chdir' внутри приложения.
  • __filename возвращает абсолютный путь к файлу, в котором он находится.
  • __dirnameвозвращает абсолютный путь к каталогу __filename.

Если вам нужно загрузить файлы из каталога вашего модуля, вам нужно использовать относительные пути.

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

вместо того

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

require(lib + '/test');

Это всегда относительно файла, из которого он был вызван, и не зависит от текущего рабочего каталога.

Вадим Барышев
источник
2
После process.chdir(), есть ли способ получить оригинал?
reergymerej
@reergymerej Вы, вероятно, захотите сначала сохранить cwd перед выполнением chdir () (например, var originalCwd = process.cwd();затем выполнить your process.chdir(), и после этого вы можете вернуться к исходному).
Swivel
это ../lib/testпортативный компьютер?
Себастьян
Нет. Это непереносимое решение, потому что Windows использует обратную косую черту. Поэтому, если вы попытаетесь запустить его в Windows, это не сработает.
zachdyer
1
Собственно для NodeJS все то же самое. Даже в Windows вы можете удобно потребовать относительные пути в стиле Unix. Таким образом, ../lib/testон переносится, в то время как аналог Windows ..\lib\test- нет ...
Кристиан Ульбрих,
48

Текущий рабочий каталог

Чтобы получить текущий рабочий каталог, вы можете использовать:

process.cwd()

Однако имейте в виду, что некоторые сценарии, особенно gulp, изменят текущий рабочий каталог на process.chdir().

Путь к модулю узла

Вы можете получить путь к текущему модулю с помощью:

  • __filename
  • __dirname

Исходный каталог (где была инициирована команда)

Если вы запускаете сценарий из командной строки и хотите, чтобы исходный каталог, из которого был запущен сценарий, независимо от того, в каком каталоге в настоящее время работает сценарий, можно использовать:

process.env.INIT_CWD

Исходный каталог, при работе со скриптами NPM

Иногда желательно запустить сценарий NPM в текущем каталоге, а не в корне проекта.

Эта переменная доступна в сценариях пакета npm как:

$INIT_CWD.

У вас должна быть последняя версия NPM. Если эта переменная недоступна, убедитесь, что NPM обновлен.

Это позволит вам получить доступ к текущему пути в вашем package.json, например:

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
superluminary
источник
process.env.INIT_CWDвозвращает package.json
режиссер
2
Осторожно, $ INIT_CWD работает только в Linux. Для Windows вам нужно будет использовать% INIT_CWD%. Я думаю, что эту проблему можно решить, используя npmjs.com/package/cross-env , но я сам не пробовал
Стефани
3

В качестве альтернативы, если вы хотите получить только текущий каталог текущего скрипта NodeJS, вы можете попробовать что-то простое, подобное этому. Обратите внимание, что это не будет работать в самом Node CLI:

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);
Джон Пол Барбагалло
источник
3

path.resolve('.')тоже надежный и чистый вариант, потому что у нас почти всегда require('path'). Он даст вам абсолютный путь к каталогу, из которого он вызван.

sziraqui
источник
0

Вот что у меня сработало:

console.log(process.mainModule.filename);
Этьен Мартин
источник