Node.js ile geçerli komut dosyasının yolunu nasıl edinebilirim?


979

Node.js'de komut dosyasının yolunu nasıl alabilirim?

Ben biliyorum process.cwd, ama bu sadece betiğin kendisinin değil, betiğin çağrıldığı dizini ifade eder. Örneğin, içinde /home/kyle/olduğumu ve aşağıdaki komutu çalıştırdığımı varsayalım:

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

Eğer ararsam process.cwd(), anlıyorum /home/kyle/, değil /home/kyle/some/dir/. Bu dizini almanın bir yolu var mı?


6
nodejs.org/docs/latest/api/globals.html kabul edilen yanıtın belge bağlantısı.
allenhwkim

Yanıtlar:


1393

Belgeleri tekrar inceledikten sonra buldum. Aradığım __filenameve __dirnamemodül düzeyindeki değişkenlerdi.

  • __filenamegeçerli modülün dosya adıdır. Bu, geçerli modül dosyasının çözümlenmiş mutlak yoludur. (örn: /home/kyle/some/dir/file.js)
  • __dirnamegeçerli modülün dizin adıdır. (örn: /home/kyle/some/dir)

3
Tam yolu değil, yalnızca dizin adını istiyorsanız, böyle bir şey yapabilirsiniz: function getCurrentDirectoryName () {var fullPath = __dirname; var path = fullPath.split ('/'); var cwd = yol [yol.uzunluk-1]; dönüş cwd; }
Anthony Martin

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

6
@Apx çözümünü deneyenler için (benim yaptığım gibi :), bu çözüm Windows üzerinde çalışmaz.
Laoujin

36
Veya sadece__dirname.split(path.sep).pop()
Burgi

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

251

Temel olarak bunu yapabilirsiniz:

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

'/' Veya '\' ile birleştirmek yerine resol () kullanın, aksi takdirde platformlar arası sorunlarla karşılaşırsınız.

Not: __dirname, modülün veya dahil edilen komut dosyasının yerel yoludur. Ana komut dosyasının yolunu bilmesi gereken bir eklenti yazıyorsanız:

require.main.filename

veya klasör adını almak için:

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

16
Amacınız sadece json dosyasını ayrıştırmak ve onunla etkileşime girmekse, bunu genellikle daha kolay yapabilirsiniz var settings = require('./settings.json'). Tabii ki, eşzamanlı fs IO, bu yüzden çalışma zamanında yapmayın, ancak başlangıç ​​zamanında iyi ve yüklendikten sonra önbelleğe alınır.
isaacs

2
@Marc Teşekkürler! Bir süredir __dirname'nin her bir modül için yerel olması gerçeği etrafında dolaşıyordum. Kütüphanemde iç içe bir yapı var ve birkaç yerde uygulamamın kökünü bilmem gerekiyor. Sevindim ben şimdi bunu nasıl yapacağını biliyorum: D
Thijs Koerselman

Düğüm V8: yol.diradı (süreç.etkiModülü.filename)
wayofthefuture

Pencerelerin gerçek bir platform olduğunu düşünmüyorsanız, çözümü atlayabilir miyiz? BSD, Macos, linux, tizen, symbian, Solaris, android, çarpıntı, webos hepsi kullanım / değil mi?
Ray Foss


119

Bu komut geçerli dizini döndürür:

var currentPath = process.cwd();

Örneğin, dosyayı okumak için yolu kullanmak üzere:

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

Eşzamansız ve Eşzamanlı'yı anlamayanlar için bu bağlantıya bakın ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
Bu tam olarak OP'nin istemediği şeydir ... istek yürütülebilir komut dosyasının yolu içindir!
caesarsol

3
Geçerli dizin çok farklı bir şey. Gibi bir şey çalıştırırsanız cd /foo; node bar/test.js, geçerli dizin olur /foo, ancak komut dosyası bulunur /foo/bar/test.js.
rjmunro

Bu iyi bir cevap değil. Bu beklediğinizden çok daha kısa bir yol olabilir bir mantık beacauese karışıklık.
kris_IV

Bunu neden hiç yaptın; dosya okuyabileceğiniz geçerli dizine göreceli ise text.txtve işe yarayacaksa, mutlak yolu oluşturmanıza gerek yoktur
Michael Mrozek

103

__Dirname kullanın !!

__dirname

Geçerli modülün dizin adı. Bu, .dosyasının path.dirname () ile aynıdır __filename.

Örnek: / Users / mjr'den node example.js çalıştırılıyor

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

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

ESModules için kullanmak istersiniz: import.meta.url


1
Bu da sembolik bağlardan kurtulur. Dolayısıyla, bir bölme oluşturursanız ve bir dosya bulmanız gerekiyorsa, örneğin path.join (__ dirname, "../example.json"); ikili kodunuz node_modules / .bin
Jason

2
Bu cevap sadece yıllar önce değil, artık ES modülleriyle de çalışmıyordu .
Dan Dascalescu

48

Ana senaryo söz konusu olduğunda:

process.argv[1]

Gönderen node.js belgelerinde :

process.argv

Komut satırı bağımsız değişkenlerini içeren bir dizi. İlk öğe 'düğüm', ikinci öğe JavaScript dosyasına giden yol olacaktır . Sonraki öğeler herhangi bir ek komut satırı bağımsız değişkeni olacaktır.

Bir modül dosyasının yolunu bilmeniz gerekiyorsa __filename kullanın .


3
Downvoter bunun neden önerilmediğini açıklayabilir mi?
Tamlyn

1
@Tamlyn Belki çalıştırılan modül dosyasını işaret process.argv[1]ederken sadece ana komut dosyası için geçerlidir __filename. Farkı vurgulamak için cevabımı güncelliyorum. Yine de, kullanırken yanlış bir şey görmüyorum process.argv[1]. Kişinin gereksinimlerine bağlıdır.
Lukasz Wiktor

10
Ana komut dosyası pm2 process.argv [1] gibi bir düğüm işlem yöneticisi ile başlatılırsa, /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

10 destekler node.js ECMAScript modüllerinin , __dirnameve __filenameartık kullanılamaz .

Daha sonra mevcut ES modülüne giden yolu kullanmak için:

import { fileURLToPath } from 'url';

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

Mevcut modülü içeren dizin için:

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

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

Bir ES modülü yazıp yazmadığımı nasıl bilebilirim? Bu yalnızca hangi Düğüm sürümünü çalıştırdığım mıydı yoksa içe aktarma / dışa aktarma anahtar kelimeleri mi kullanıyorsam?
Ed Brannin

2
ES modülleri yalnızca --experimental-modulesbayrakla kullanılabilir.
Nickensoul

1
- deneysel modüller yalnızca düğüm sürümü <13.2 olarak çalıştırıyorsanız gereklidir. dosyayı .js yerine .mjs olarak adlandırın
Brent



13

Bunun oldukça eski olduğunu biliyorum ve yanıtladığım orijinal soru yineleniyor ve burada yönlendiriliyor, ancak yasemin muhabirlerinin çalışmasını sağlamakla ilgili bir sorunla karşılaştım ve içeriyi düşürmek zorunda olduğum fikrini beğenmedim çalışması için emir verin. Yasemin-gazetecilerin savePath'i doğru bir şekilde çözmediğini ve aslında gulp çalıştırdığım kök dizin yerine jasmine-reporters dizinine raporlar klasörü çıktısı koyduğunu öğrendim. Bu düzgün çalışması için gulp koştu dizini olması gereken ilk Geçerli Çalışma Dizini almak için process.env.INIT_CWD kullanarak sona erdi . Umarım bu birine yardımcı olur.

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

8

Geçerli uygulama klasörü yolunu almak için process.env.PWD dosyasını kullanabilirsiniz.


2
OP istenen "komut dosyasının yolu" nu sorar. Süreç Çalışma Dizini gibi bir şey anlamına gelen PWD bu değildir. Ayrıca, "mevcut uygulama" ifadesi yanıltıcıdır.
dmcontador

7

pkgUygulamanızı paketlemek için kullanıyorsanız , bu ifadeyi yararlı bulacaksınız:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkguygulamanın paketlenip paketlenmediğini söyler pkg.

  • process.execPath, /usr/bin/nodekomut dosyalarının ( node test.js) veya doğrudan paketin çağrılması için olan veya benzeri yürütülebilir dosyanın tam yolunu tutar .

  • require.main.filename ana komut dosyasının tam yolunu tutar, ancak Düğüm etkileşimli modda çalıştığında boş olur.

  • __dirnamegeçerli betiğin tam yolunu tutar , bu yüzden kullanmıyorum (OP'nin istediği olmasına rağmen; appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));etkileşimli modda __dirnameboş olduğunu belirterek daha iyi kullanın .

  • Etkileşimli mod process.argv[0]için, Düğüm yürütülebilir dosyasının yolunu process.cwd()almak veya geçerli dizini almak için kullanın.


3

Modül basenameyöntemini kullanın path:

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

İşte yukarıdaki örnek alınır dokümandır.

Dan'ın işaret ettiği gibi, Düğüm "- deneysel modüller" bayrağıyla ECMAScript modülleri üzerinde çalışıyor . Düğüm 12 hala destekliyor __dirnameve__filename yukarıdaki gibi.


--experimental-modulesBayrağı kullanıyorsanız, alternatif bir yaklaşım var .

Alternatif, mevcut ES modülüne giden yolu elde etmektir :

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

Mevcut modülü içeren dizin için:

import path from 'path';

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

-2

Bir kabuk komut dosyasında $ 0 gibi bir şey istiyorsanız şunu deneyin:

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

__dirnameve __filenamevardır artık ES modülleriyle kullanılabilir .
Dan Dascalescu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.