Как получить путь к текущему script с помощью Node.js?

Как мне получить путь к script в Node.js?

Я знаю там process.cwd, но это относится только к каталогу, в котором был вызван script, а не самому script. Например, скажем, что я в /home/kyle/, и я запускаю следующую команду:

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

Если я вызываю process.cwd(), я получаю /home/kyle/, а не /home/kyle/some/dir/. Есть ли способ получить этот каталог?

Ответ 1

Я нашел это после просмотра документации снова. Я искал переменные уровня модуля __filename и __dirname.

  • __filename - имя файла текущего модуля. Это разрешенный абсолютный путь к текущему файлу модуля. (например: /home/kyle/some/dir/file.js)
  • __dirname - имя каталога текущего модуля. (напр.: /home/kyle/some/dir)

Ответ 2

Итак, в основном вы можете это сделать:

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

Используйте параметр resolve() вместо конкатенации с помощью '/' или '\', иначе вы столкнетесь с кросс-платформенными проблемами.

Примечание. __dirname - это локальный путь модуля или включен script. Если вы пишете плагин, который должен знать путь к главному script, это:

require.main.filename

или, чтобы просто получить имя папки:

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

Ответ 3

Эта команда возвращает текущий каталог:

var currentPath = process.cwd();

Например, чтобы использовать путь для чтения файла:

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

Ответ 4

Используйте __dirname !!

__dirname

Имя каталога текущего модуля. Это так же, как path.dirname() __filename.

Пример: запуск узла example.js из /Users/mjr

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

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

Для ESModules вы хотели бы использовать: import.meta.url

Ответ 5

Когда дело доходит до основного скрипта, это так просто:

process.argv[1]

Из документации Node.js:

process.argv

Массив, содержащий аргументы командной строки. Первым элементом будет "узел", вторым элементом будет путь к файлу JavaScript. Следующими элементами будут любые дополнительные аргументы командной строки.

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

Ответ 6

var settings = 
    JSON.parse(
        require('fs').readFileSync(
            require('path').resolve(
                __dirname, 
                'settings.json'),
            'utf8'));

Ответ 7

Каждая программа Node.js имеет некоторые глобальные переменные в своей среде, которая представляет некоторую информацию о вашем процессе, а одна из них - __dirname.

Ответ 8

Node.js 10 поддерживает модули ECMAScript, где __dirname и __filename больше не доступны.

Затем, чтобы получить путь к текущему модулю ES, нужно использовать:

import { fileURLToPath } from 'url';

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

А для каталога, содержащего текущий модуль:

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

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

Ответ 9

Вы можете использовать process.env.PWD, чтобы получить текущий путь к папке приложения.

Ответ 10

Я знаю, что это довольно старый, и исходный вопрос, на который я отвечал, отмечен как дубликат и направлен здесь, но я столкнулся с проблемой, пытаясь заставить жасмин-репортеров работать, и мне не понравилась идея о том, что я для понижения, чтобы он работал. Я узнал, что жасмин-репортеры не правильно разрешали savePath и фактически помещали вывод папок отчетов в каталог жасмин-репортеров вместо корневого каталога, где я запускал gulp. Чтобы сделать эту работу правильно, я закончил использование process.env.INIT_CWD, чтобы получить начальный текущий рабочий каталог, который должен быть каталогом, в котором вы запустили gulp. Надеюсь, это поможет кому-то.

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

Ответ 11

Если вы используете pkg для упаковки своего приложения, вы найдете это выражение следующим:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkg указывает, было ли приложение упаковано с помощью pkg.

  • process.execPath содержит полный путь исполняемого файла, который является /usr/bin/node или аналогичным для прямых вызовов скриптов (node test.js) или упакованного приложения.

  • require.main.filename содержит полный путь к основному script, но он пуст, когда Node работает в интерактивном режиме.

  • __dirname содержит полный путь к текущему script, поэтому я его не использую (хотя может быть и то, что ОП спрашивает, а затем лучше использовать appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));, отмечая, что в интерактивном режиме __dirname пусто.

  • Для интерактивного режима используйте process.argv[0], чтобы получить путь к исполняемому файлу Node или process.cwd(), чтобы получить текущий каталог.

Ответ 12

Используйте метод basename модуля path:

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

Вот документация, из которой взят пример выше.

Как отметил Дэн, Node работает над модулями ECMAScript с флагом --experimental-modules. Узел 12 все еще поддерживает __dirname и __filename как указано выше.


Если вы используете флаг --experimental-modules, есть альтернативный подход.

Альтернативой является получение пути к текущему модулю ES:

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

А для каталога, содержащего текущий модуль:

import path from 'path';

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

Ответ 13

Если вам нужно нечто вроде $0 в оболочке script, попробуйте следующее:

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