현재 실행중인 파일의 디렉토리를 얻는 방법?


239

nodejs에서는 __dirname을 사용 합니다 . Golang에서 이에 상응하는 것은 무엇입니까?

나는 googled 하고이 기사 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을 반복해서 실행하지 않도록 전역 var (파일 위치를 실행할 수 없습니다 :) 경로를 캐시 할 수 있습니다
oguzalb

로 전달 0하지 않아야 1합니다 runtime.Caller().
fiatjaf

4
runtime.Caller(0)소스 파일의 경로를 알려줍니다 $GOPATH/src/packagename/main.go. 이 스레드의 다른 답변은 실행 파일의 경로를 반환하려고합니다 (예 :) $GOPATH/bin/packagename.
fiatjaf

프로그램이 파일에서 실행되고 있다고 가정합니다.
Flimzy

답변:


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
여기에 오류가있을 수 있습니까? 그렇다면 호기심으로 인해 오류가 무엇입니까?
Jeff Escalante

4
나를 위해 작동하지 않습니다 play.golang.org/p/c8fe-Zm_bH 반드시 복근 경로를 포함하지 않는 os.Args [0] -.
zupa

5
os.Args [0]에 abs 경로가없는 경우에도 실제로 작동합니다. 놀이터 결과가 예상과 다른 이유는 샌드 박스 안에 있기 때문입니다.
Gustavo Niemeyer

37
이것은 신뢰할 수있는 방법이 아닙니다. osext 사용에 대한 답변은 다양한 OS에서 모든 클라이언트와 작동하는 구현 이었으므로 참조하십시오 . 이 방법을 사용하여 코드를 구현했지만 매우 안정적이지 않은 것으로 보이며 많은 사용자 가이 방법으로 인해 실행 파일의 경로를 잘못 선택했기 때문에 버그에 대해 불평했습니다.
JD D

5
Windows에서 Go 1.6을 사용하여 emrah와 동일한 결과를 얻었습니다 (소스 파일 폴더 대신 임시 폴더의 경로가 있음). 외부 의존성을 사용하지 않고 소스 파일 폴더의 경로를 얻으려면 OP 코드의 _, currentFilePath, _, _ := runtime.Caller(0) dirpath := path.Dir(currentFilePath)runtime.Caller(0)runtime.Caller(1)
약간

295

편집 : Go 1.8 (2017 년 2 월 릴리스) 현재 권장되는 방법은 다음과 os.Executable같습니다.

func Executable() (string, error)

실행 파일은 현재 프로세스를 시작한 실행 파일의 경로 이름을 반환합니다. 경로가 여전히 올바른 실행 파일을 가리키고 있다는 보장은 없습니다. 운영 체제에 따라 symlink를 사용하여 프로세스를 시작한 경우 결과는 symlink 또는 지정된 경로 일 수 있습니다. 안정적인 결과가 필요한 경우 path / filepath.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
현재 프로세스 작업 디렉토리입니다. nodejs에서는 process.cwd ()와 같습니다. nodejs.org/api/process.html#process_process_cwd
ekanna

2
좋아, 나는 구별을 본다. 현재 작업 디렉토리가 아닌 filesytem에서 바이너리 위치를 runtime.Caller
찾은 후

3
'2017 년 2 월 릴리스'? 타임머신이 발명 된 것 같습니다. 앞으로 회원이 게시됩니다. 향후 버전에 신뢰할 수있는 크로스 플랫폼 방법이있을 것입니다. 한편 현재 사용 가능한 솔루션을 고수해야합니다.
ljgww

1
@ljgww 죄송합니다. Delorean을 가져 가서 집에 갈 것입니다 :-) 예정된 기능 만보고 나중에 답변을 업데이트하는 것을 잊어 버렸기 때문에 미리 답변을 업데이트했습니다.
Intermernet

1
슬래시 (Unix 스타일)와 함께 디렉토리 구분 기호로만 작동 path/filepath.Dir하므로 편집했습니다 path.Dir.
Jocelyn

63

패키지 osext 사용

ExecutableFolder()현재 실행중인 프로그램 실행 파일이있는 폴더의 절대 경로를 반환 하는 기능 을 제공 합니다 (cron 작업에 유용함). 크로스 플랫폼입니다.

온라인 문서

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
이것은 Windows와 Linux에서 나에게 기대되는 결과를 가져온 유일한 대답입니다.
DannyB

3
go run main.go로컬 개발 에 사용할 때까지 잘 작동합니다 . 매번 실행 파일을 미리 작성하지 않고 어떻게 해결할 수 있는지 잘 모르겠습니다.
Derek Dowling

1
작동 방법을 모르겠습니다 go run. 이 바이너리는 매번 임시 폴더에 저장됩니다.
Dobrosław Żybort

2
@DerekDowling 방법은 먼저 go install다음을 실행하는 것 go build -v *.go && ./main입니다. 는 -v파일이 내장되고있는 당신에게 말할 것이다. 일반적으로, 나는 이미 실행 한 경우 사이에 다른 시간 go rungo build허용 되는 것을 발견했습니다 go install. PowerShell을 윈도우 사용자의 경우, 명령이 될 것입니다go build -v {*}.go && ./main.exe
kumarharsh

이것이 반환되므로 $GOPATH/bin/왜 사용하지 $GOPATH/bin/않습니까?
fiatjaf

10
filepath.Abs("./")

Abs는 경로의 절대 표현을 반환합니다. 경로가 절대 경로가 아닌 경우 현재 작업 디렉토리와 결합되어 절대 경로로 바뀝니다.

주석에 언급 된대로 현재 활성화 된 디렉토리를 반환합니다.


8
현재 파일의 디렉토리가 아닌 현재 디렉토리를 반환합니다. 예를 들어, 실행 파일이 다른 경로에서 호출 된 경우에는 달라집니다.
Fujii

8

이 방법을 사용하면 :

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

실행 파일은 / tmp에서 저장 및 실행되므로 GoLang과 같은 일부 IDE를 사용하여 프로그램을 실행할 때 / tmp 경로를 얻습니다.

현재 작업 디렉토리 또는 '.'을 얻는 가장 좋은 방법이라고 생각합니다. 입니다 :

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

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

os.Getwd () 함수는 현재 작업 디렉토리를 반환합니다. 외부 라이브러리를 사용하지 않고 모든 것 : D


이것은 정확하지 않습니다. 이것은 파일의 디렉토리가 아닌 프로세스를 실행하는 사용자의 작업 디렉토리를 리턴합니다. filepath.abs를 사용하십시오.
PodTech.io

1
실행중인 실행 파일의 작업 디렉토리를 반환합니다. 그런 다음 goland와 같은 IDE를 사용하고 있으며 빌드 옵션에 작업 디렉토리에 대한 구성이 없으면 / tmp에서 실행되며 / tmp의 사용법은 무엇입니까 ??? 그러나 os.Getwd ()를 사용하는 경우 .exe 또는 elf 실행 파일 경로를 반환합니다. / tmp가 아닙니다.
비트

@Bit 그런 IDE에서 디버깅의 기본 템플릿을 사용하면, 예를 들어 'Edit Configuration'을 누르고 'Output Directory'를 채우면 'os.Args [0]'경로가 원하는 것입니다.
ϻα youɾΣɀО -MaMrEzO

5

당신이 패키지를 사용하는 경우 osext 에 의해 kardianos을 데릭 다울 링은 주석처럼 당신은 로컬 테스트해야합니다 :

이것은 로컬 개발을 위해 go run main.go와 함께 사용할 때까지 잘 작동합니다. 매번 실행 파일을 미리 작성하지 않고 어떻게 해결할 수 있는지 잘 모르겠습니다.

이에 대한 해결책은 go run을 사용하는 대신 gorun.exe 유틸리티를 만드는 것입니다. gorun.exe 유틸리티는 "go build"를 사용하여 프로젝트를 컴파일 한 다음 프로젝트의 일반 디렉토리에서 바로 실행합니다.

나는 다른 컴파일러와 함께이 문제가 있었고 컴파일러와 함께 제공되지 않기 때문에이 유틸리티를 만드는 것을 발견했습니다 ... 특히 C와 같은 도구를 사용하여 컴파일하고 링크 한 다음 실행해야합니다 (너무 많은 작업).

gorun.exe (또는 elf)에 대한 아이디어가 마음에 든다면 곧 github에 업로드 할 것입니다.

죄송합니다.이 답변은 의견입니다.하지만 아직 평판이 좋지 않아서 댓글을 달 수 없습니다.

또는 "go run"을 수정하여 (이 기능이없는 경우) "go run -notemp"와 같은 매개 변수를 사용하여 임시 디렉토리 (또는 이와 유사한 것)에서 프로그램을 실행하지 않을 수 있습니다. 그러나 복잡한 매개 변수보다 짧으므로 gorun 또는 "gor"을 입력하는 것이 좋습니다. Gorun.exe 또는 gor.exe는 go 컴파일러와 동일한 디렉토리에 설치해야합니다.

gorun.exe (또는 gor.exe)를 구현하는 것은 몇 줄의 코드로 다른 컴파일러와 함께 했으므로 간단합니다 ... (유명한 마지막 단어 ;-)


3
"go run"으로 작업하고 실행 파일을 빌드하려면 간단히 _, callerFile, _, _ := runtime.Caller(0) executablePath := filepath.Dir(callerFile)대신 사용하십시오
Jocelyn

@Jocelyn, 귀하의 의견은 너무 커서 전체 답변으로 작성해야합니다! 이것은 확실히 나를 위해 속임수를 썼다-내 자신의 설정에서, 나는 macOS에 환경의 로컬 사본을 가지고 있는데, 나는 주로 구문 오류 (및 몇 가지 의미 론적 오류)를 잡기 위해 사용한다. 그런 다음 코드를 Ubuntu Linux에서 실행되는 배포 서버에 동기화하고 물론 환경이 완전히 다릅니다 ... 그래서 파일 경로가 템플릿, 구성 파일, 정적을 올바르게로드하는 위치를 알아야합니다. 파일 등 ...
Gwyneth Llewelyn


4

때로는 이것으로 충분합니다. 첫 번째 인수는 항상 파일 경로입니다.

package main

import (
    "fmt"
    "os"
)


func main() {
    fmt.Println(os.Args[0])

    // or
    dir, _ := os.Getwd()
    fmt.Println(dir)
}

0

Gustavo Niemeyer의 답변은 훌륭합니다. 그러나 Windows에서 런타임 proc은 주로 다음과 같은 다른 디렉토리에 있습니다.

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

과 같은 상대 파일 경로를 사용하면 "/config/api.yaml"코드가 존재하는 프로젝트 경로가 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.