वर्तमान में चल रही फ़ाइल की निर्देशिका कैसे प्राप्त करें?


239

नोडज में मैं __dirname का उपयोग करता हूं । गोलंग में इसके बराबर क्या है?

मैंने गुगली की है और इस लेख का पता लगाया है http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/ । जहां वह नीचे दिए गए कोड का उपयोग करता है

_, filename, _, _ := runtime.Caller(1)
f, err := os.Open(path.Join(path.Dir(filename), "data.csv"))

लेकिन क्या यह गोलंग में करने का सही तरीका या मुहावरेदार तरीका है?


यह आपके प्रश्न का उत्तर नहीं है, लेकिन आप एक वैश्विक संस्करण के लिए पथ को कैश कर सकते हैं (दौड़ते समय आपकी फ़ाइल स्थान को बदला नहीं जा सकता है :)) os.open को चलाने के लिए नहीं फिर से और हर बार जब आपका कोड चलता है
oguzalb

उत्तीर्ण होने चाहिए 0नहीं, 1, करने के लिए runtime.Caller()
फिएटजैफ

4
runtime.Caller(0)आप, स्रोत फ़ाइल का रास्ता दे देंगे की तरह $GOPATH/src/packagename/main.go। इस थ्रेड के अन्य उत्तर निष्पादन योग्य (जैसे $GOPATH/bin/packagename) पथ को वापस करने का प्रयास कर रहे हैं ।
फिएटजैफ

आप मान रहे हैं कि प्रोग्राम एक फाइल से चल रहा है ...
फ्लिमज़ी

जवाबों:


221

यह करना चाहिए:

import (
    "fmt"
    "log"
    "os"
    "path/filepath"
)

func main() {
    dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    if err != nil {
            log.Fatal(err)
    }
    fmt.Println(dir)
}

2
क्या यहां त्रुटि होना संभव है? यदि हां, तो क्या त्रुटि होगी, बस जिज्ञासा से बाहर?
जेफ एस्क्लांते

4
मेरे लिए काम नहीं करता है। play.golang.org/p/c8fe-Zm_bH - os.Args [0] जरूरी नहीं कि एब्स पाथ हो।
zupa

5
यह वास्तव में काम करता है भले ही os.Args [0] में एब्स पथ न हो। खेल के मैदान का परिणाम वह नहीं है जिसकी आपको उम्मीद थी क्योंकि यह सैंडबॉक्स के अंदर है।
गुस्तावो नीमेयर

37
यह एक विश्वसनीय तरीका नहीं है , osext का उपयोग करने के बारे में उत्तर देखें क्योंकि यह कार्यान्वयन था जो हमारे सभी ग्राहकों के साथ विभिन्न ओएस पर काम करता था। मैंने इस पद्धति का उपयोग करके कोड लागू किया था, लेकिन यह बहुत विश्वसनीय नहीं लगता है और कई उपयोगकर्ताओं ने बग की शिकायत की है जो इस विधि के कारण निष्पादन योग्य के लिए गलत रास्ता चुनते हैं।
JD D

5
Windows पर Go 1.6 का उपयोग करके emrah के समान परिणाम प्राप्त करें (स्रोत फ़ाइल फ़ोल्डर के बजाय अस्थायी फ़ोल्डर का पथ मिला)। किसी भी बाहरी निर्भरता का उपयोग किए बिना अपने स्रोत फ़ाइल के फ़ोल्डर का पथ प्राप्त करने के लिए, ओपी के कोड का _, currentFilePath, _, _ := runtime.Caller(0) dirpath := path.Dir(currentFilePath)runtime.Caller(0)runtime.Caller(1)
थोड़ा

295

EDIT: गो १. (के रूप में (फरवरी २०१ Go को जारी) ऐसा करने का अनुशंसित तरीका इस प्रकार है os.Executable:

func Executable() (string, error)

निष्पादन योग्य निष्पादन योग्य के लिए पथ का नाम देता है जिसने वर्तमान प्रक्रिया शुरू की थी। इस बात की कोई गारंटी नहीं है कि रास्ता अभी भी सही निष्पादन योग्य होने की ओर इशारा कर रहा है। यदि ऑपरेटिंग सिस्टम के आधार पर, प्रक्रिया शुरू करने के लिए एक सिमलिंक का उपयोग किया गया था, तो परिणाम सिम्लिंक या उस पथ को इंगित कर सकता है जो उसने बताया था। यदि एक स्थिर परिणाम की आवश्यकता होती है, तो पथ / फ़ाइलपथ। EvalSymlinks मदद कर सकता है।

निष्पादन योग्य की केवल निर्देशिका प्राप्त करने के लिए आप उपयोग कर सकते हैं path/filepath.Dir

उदाहरण :

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    ex, err := os.Executable()
    if err != nil {
        panic(err)
    }
    exPath := filepath.Dir(ex)
    fmt.Println(exPath)
}

पुराने उत्तर:

आप का उपयोग करने में सक्षम होना चाहिए os.Getwd

func Getwd() (pwd string, err error)

Getwd वर्तमान निर्देशिका के अनुरूप एक मूल पथ नाम देता है। यदि वर्तमान निर्देशिका को कई रास्तों (प्रतीकात्मक लिंक के कारण) के माध्यम से पहुँचा जा सकता है, तो Getwd उनमें से किसी एक को वापस कर सकता है।

उदाहरण के लिए:

package main

import (
    "fmt"
    "os"
)

func main() {
    pwd, err := os.Getwd()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(pwd)
}

3
यह वर्तमान कार्यशील निर्देशिका है। नोडज में यह process.cwd () के बराबर है। ( ndjs.org/api/process.html#process_process_cwd
ekanna

2
ठीक है, मैं भेद देखता हूं। आप फाइलसीटम में बाइनरी के स्थान के बाद हैं (वर्तमान कार्यशील निर्देशिका के बजाय) मुझे लगता है कि runtime.Callerआप "मुहावरेदार" के सबसे करीब होंगे
इंटरमरनेट

3
'फरवरी 2017 को रिलीज़ ’? ऐसा लगता है कि समय मशीन का आविष्कार किया गया है और हमारे पास भविष्य से पोस्ट करने वाले सदस्य हैं। यह जानना अच्छा है कि भविष्य के संस्करण में विश्वसनीय क्रॉस प्लेटफ़ॉर्म विधि होगी, इस बीच हमें वर्तमान में उपलब्ध समाधानों से चिपके रहना होगा।
ljgww

1
@ljgww क्षमा करें, मैं अपना डेलोरियन ले जाऊंगा और घर जाऊंगा :-) मैंने अपना उत्तर पहले ही अपडेट कर दिया था क्योंकि मैंने केवल उस आगामी सुविधा को देखा था और लगा कि मैं बाद में उत्तर को अपडेट करना भूल जाऊंगा।
इंटरमरनेट

1
के साथ संपादित path/filepath.Dirक्योंकि path.Dirकेवल फॉरवर्ड स्लैश (यूनिक्स शैली) के साथ निर्देशिका विभाजकों के रूप में काम करता है।
जॉचलीएन

63

पैकेज osext का उपयोग करें

यह फ़ंक्शन प्रदान ExecutableFolder()कर रहा है जो फ़ोल्डर के लिए एक पूर्ण पथ देता है जहां वर्तमान में चल रहे कार्यक्रम निष्पादन योग्य निवास (क्रोन नौकरियों के लिए उपयोगी) है। यह क्रॉस प्लेटफॉर्म है।

ऑनलाइन दस्तावेजीकरण

package main

import (
    "github.com/kardianos/osext"
    "fmt"
    "log"
)

func main() {
    folderPath, err := osext.ExecutableFolder()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(folderPath)
}

13
यह एकमात्र उत्तर है जिसने विंडोज और लिनक्स दोनों पर मेरे लिए अपेक्षित परिणाम उत्पन्न किए।
डैनीबी

3
यह तब तक ठीक रहता है जब तक कि आप इसे go run main.goस्थानीय विकास के लिए उपयोग नहीं करना चाहते । सुनिश्चित नहीं है कि हर बार पहले से एक निष्पादन योग्य निर्माण के बिना चारों ओर पाने के लिए सबसे अच्छा कैसे हो।
डेरेक डॉवलिंग

1
क्षमा करें, मुझे नहीं पता कि इसे कैसे काम करना है go run। इस बायनेरी को हर बार अस्थायी फ़ोल्डर में रखा जाता है।
डोब्रोस्लाव ortयबोर्ट

2
@DerekDowling एक तरह से पहले एक कर रहा होगा go install, फिर चल रहा है go build -v *.go && ./main-vआपको बता होगा जो फ़ाइलों का निर्माण किया जा रहा है। आम तौर पर, मैंने पाया है कि अगर मैंने पहले ही दौड़ लिया है तो बीच का समय अलग है go runऔर go buildसहनीय है go installgo build -v {*}.go && ./main.exe
पावरशेल

चूंकि यह वापस आ जाएगा $GOPATH/bin/, इसलिए उपयोग क्यों नहीं $GOPATH/bin/?
फिएटजैफ

10
filepath.Abs("./")

Abs पथ का पूर्ण प्रतिनिधित्व देता है। यदि पथ निरपेक्ष नहीं है, तो इसे पूर्ण पथ में बदलने के लिए इसे वर्तमान कार्य निर्देशिका के साथ जोड़ा जाएगा।

जैसा कि टिप्पणी में कहा गया है, यह उस निर्देशिका को लौटाता है जो वर्तमान में सक्रिय है।


8
यह वर्तमान निर्देशिका को लौटाता है, वर्तमान फ़ाइल की निर्देशिका को नहीं। उदाहरण के लिए, यह अलग होगा यदि निष्पादन योग्य को एक अलग पथ से बुलाया गया था।
फूजी

8

यदि आप इस तरह से उपयोग करते हैं:

dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
    log.Fatal(err)
}
fmt.Println(dir)

जब आप GoLang जैसे कुछ IDE का उपयोग करके प्रोग्राम चला रहे हों, तो आपको / tmp का रास्ता मिल जाएगा क्योंकि निष्पादन योग्य बचत होगी और /mp को रन करेगा

मुझे लगता है कि करंट वर्किंग डायरेक्टरी या 'पाने का सबसे अच्छा तरीका है।' है :

import(
  "os" 
  "fmt"
  "log"
)

func main() {
  dir, err := os.Getwd()
    if err != nil {
        log.Fatal(err)
    }
  fmt.Println(dir)
}

os.Getwd () समारोह वर्तमान कार्यशील निर्देशिका वापस आ जाएगी। और किसी भी बाहरी पुस्तकालय का उपयोग किए बिना इसके सभी: डी


यह सही नहीं है। यह प्रक्रिया को निष्पादित करने वाले उपयोगकर्ता की कार्यशील निर्देशिका को लौटाता है न कि फ़ाइल की निर्देशिका को। Filepath.abs का उपयोग करें।
पॉडटेक.आईओ

1
यह चल रहे निष्पादन योग्य फ़ाइल की कार्यशील निर्देशिका को लौटाता है। फिर यदि आप एक आईडीई जैसे गॉलैंड का उपयोग कर रहे हैं और बिल्ड ऑप्शंस में वर्किंग डायरेक्टरी के लिए कोई कॉन्फिगर नहीं है तो यह / tmp से चलेगा, फिर आपके लिए क्या उपयोग / tmp है! ?? लेकिन अगर आप os.Getwd () का उपयोग करते हैं! .exe या योगिनी निष्पादन योग्य फ़ाइल पथ देता है। नहीं / tmp।
बिट

@ इस तरह के आईडीई में डिबगिंग के बेस टेम्प्लेट का उपयोग करके, हाँ, आपको वह देता है, तो बस 'कॉन्फ़िगरेशन संपादित करें' और 'आउटपुट डायरेक्टरी' भरें, इसलिए आपको 'os.Args [0]' पथ दिखाई देगा, जिसे आप चाहते हैं
ϻɾΣɀα templateО -MMEEzO

5

यदि आप kardianos द्वारा पैकेज osext का उपयोग करते हैं और आपको स्थानीय रूप से परीक्षण करने की आवश्यकता है, जैसे डेरेक डॉवलिंग ने टिप्पणी की:

यह तब तक ठीक रहता है जब तक कि आप इसे स्थानीय विकास के लिए मुख्य रन-वे के साथ उपयोग करना चाहते हैं। सुनिश्चित नहीं है कि हर बार पहले से ही एक निष्पादन योग्य निर्माण के बिना आसपास कितना अच्छा हो।

इसका समाधान गो रन का उपयोग करने के बजाय एक gorun.exe उपयोगिता बनाना है। Gorun.exe उपयोगिता प्रोजेक्ट को "गो बिल्ड" का उपयोग करके संकलित करेगी, फिर अपने प्रोजेक्ट की सामान्य निर्देशिका में इसे ठीक बाद में चलाएं।

मेरे पास अन्य कंपाइलरों के साथ यह समस्या थी और मैंने खुद को इन उपयोगिताओं को बनाते हुए पाया, क्योंकि वे कंपाइलर के साथ शिप नहीं किए गए हैं ... यह विशेष रूप से सी जैसे टूल के साथ है जहां आपको कंपाइल करना और लिंक करना है और फिर इसे (बहुत अधिक काम) चलाना है।

अगर किसी को भी gorun.exe (या योगिनी) का मेरा विचार पसंद आया, तो मैं इसे जल्द ही github पर अपलोड करूँगा।

क्षमा करें, यह उत्तर एक टिप्पणी के रूप में है, लेकिन मेरे कारण अभी तक एक बड़ी प्रतिष्ठा नहीं होने के कारण मैं टिप्पणी नहीं कर सकता।

वैकल्पिक रूप से, "गो रन" को संशोधित किया जा सकता है (यदि इसमें पहले से यह सुविधा नहीं है) तो एक अस्थायी निर्देशिका (या कुछ इसी तरह) में कार्यक्रम को नहीं चलाने के लिए "गो रन -पेंटेम" जैसे पैरामीटर होना चाहिए। लेकिन मैं सिर्फ गोरून या "गोर" लिखना पसंद करूंगा क्योंकि यह एक जटिल पैरामीटर से कम है। Gorun.exe या gor.exe को आपके गो संकलक के समान निर्देशिका में स्थापित करना होगा

Gorun.exe (या gor.exe) को लागू करना तुच्छ होगा, जैसा कि मैंने इसे कोड के कुछ ही पंक्तियों में अन्य संकलक के साथ किया है ... (प्रसिद्ध अंतिम शब्द ;-)


3
यदि आप इसे "गो रन" के साथ काम करना चाहते हैं और निष्पादन योग्य बनाया गया है, तो _, callerFile, _, _ := runtime.Caller(0) executablePath := filepath.Dir(callerFile)इसके बजाय बस का उपयोग करें
Jocelyn

@ जान, आपकी टिप्पणी इतनी शानदार है कि आपको इसे पूर्ण उत्तर देना चाहिए! यह निश्चित रूप से मेरे लिए चाल है - अपने स्वयं के सेटअप पर, मेरे पास macOS में पर्यावरण की एक स्थानीय प्रतिलिपि है, जिसका उपयोग मैं ज्यादातर वाक्यविन्यास त्रुटियों (और कुछ अर्थ वाले) को पकड़ने के लिए करता हूं; फिर मैं कोड को परिनियोजन सर्वर पर सिंक करता हूं, जो उबंटू लिनक्स के तहत चलता है, और निश्चित रूप से वातावरण पूरी तरह से अलग है ... इसलिए यह पता लगाने की एक वास्तविक आवश्यकता है कि फ़ाइल पथ ठीक से टेम्पलेट्स, कॉन्फ़िगरेशन फ़ाइलों, स्थिर लोड करने के लिए कहां हैं फ़ाइलें, आदि ...
Gwyneth Llewelyn

4

os.Executable: https://tip.golang.org/pkg/os/#Executable

filepath.EvalSymlinks: https://golang.org/pkg/path/filepath/#EvalSymlinks

पूर्ण डेमो:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    var dirAbsPath string
    ex, err := os.Executable()
    if err == nil {
        dirAbsPath = filepath.Dir(ex)
        fmt.Println(dirAbsPath)
        return
    }

    exReal, err := filepath.EvalSymlinks(ex)
    if err != nil {
        panic(err)
    }
    dirAbsPath = filepath.Dir(exReal)
    fmt.Println(dirAbsPath)
}


0

गुस्तावो नीमेयर का जवाब बहुत अच्छा है। लेकिन विंडोज में, रनटाइम की खरीद ज्यादातर इस तरह से होती है:

"C:\Users\XXX\AppData\Local\Temp"

यदि आप सापेक्ष फ़ाइल पथ "/config/api.yaml"का उपयोग करते हैं , जैसे , यह आपके प्रोजेक्ट पथ का उपयोग करेगा जहाँ आपका कोड मौजूद है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.