How to get the directory of the currently running file?

Go

Go Problem Overview


In nodejs I use __dirname . What is the equivalent of this in Golang?

I have googled and found out this article http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/ . Where he uses below code

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

But is it the right way or idiomatic way to do in Golang?

Go Solutions


Solution 1 - Go

EDIT: As of Go 1.8 (Released February 2017) the recommended way of doing this is with os.Executable:

>func Executable() (string, error) > >Executable returns the path name for the executable that started the current process. There is no guarantee that the path is still pointing to the correct executable. If a symlink was used to start the process, depending on the operating system, the result might be the symlink or the path it pointed to. If a stable result is needed, path/filepath.EvalSymlinks might help.

To get just the directory of the executable you can use path/filepath.Dir.

Example:

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

OLD ANSWER:

You should be able to use os.Getwd

func Getwd() (pwd string, err error)

>Getwd returns a rooted path name corresponding to the current directory. If the current directory can be reached via multiple paths (due to symbolic links), Getwd may return any one of them.

For example:

package main

import (
    "fmt"
    "os"
)

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

Solution 2 - Go

This should do it:

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

Solution 3 - Go

Use package osext

It's providing function ExecutableFolder() that returns an absolute path to folder where the currently running program executable reside (useful for cron jobs). It's cross platform.

Online documentation

package main

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

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

Solution 4 - Go

filepath.Abs("./")

> Abs returns an absolute representation of path. If the path is not > absolute it will be joined with the current working directory to turn > it into an absolute path.

As stated in the comment, this returns the directory which is currently active.

Solution 5 - Go

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

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

Full Demo:

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

Solution 6 - Go

if you use this way :

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

you will get the /tmp path when you are running program using some IDE like GoLand because the executable will save and run from /tmp

i think the best way for getting the currentWorking Directory or '.' is :

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

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

the os.Getwd() function will return the current working directory. and its all without using of any external library :D

Solution 7 - Go

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

this is for golang version: go version go1.13.7 linux/amd64

works for me, for go run main.go. If I run go build -o fileName, and put the final executable in some other folder, then that path is given while running the executable.

Solution 8 - Go

If you use package osext by kardianos and you need to test locally, like Derek Dowling commented:

> This works fine until you'd like to use it with go run main.go for > local development. Not sure how best to get around that without > building an executable beforehand each time.

The solution to this is to make a gorun.exe utility instead of using go run. The gorun.exe utility would compile the project using "go build", then run it right after, in the normal directory of your project.

I had this issue with other compilers and found myself making these utilities since they are not shipped with the compiler... it is especially arcane with tools like C where you have to compile and link and then run it (too much work).

If anyone likes my idea of gorun.exe (or elf) I will likely upload it to github soon..

Sorry, this answer is meant as a comment, but I cannot comment due to me not having a reputation big enough yet.

Alternatively, "go run" could be modified (if it does not have this feature already) to have a parameter such as "go run -notemp" to not run the program in a temporary directory (or something similar). But I would prefer just typing out gorun or "gor" as it is shorter than a convoluted parameter. Gorun.exe or gor.exe would need to be installed in the same directory as your go compiler

Implementing gorun.exe (or gor.exe) would be trivial, as I have done it with other compilers in only a few lines of code... (famous last words ;-)

Solution 9 - Go

Sometimes this is enough, the first argument will always be the file path

package main

import (
	"fmt"
	"os"
)


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

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

Solution 10 - Go

I came from Node.js to Go. The Node.js equivalent to __dirname in Go is:

_, filename, _, ok := runtime.Caller(0)
if !ok {
	return nil, errors.New("unable to get the current filename")
}
dirname := filepath.Dir(file)

Some other mentions in this thread and why they're wrong:

  • os.Executable() will give you the filepath of the currently running executable. This is equivalent to process.argv[0] in Node. This is not true if you want to take the __dirname of a sub-package.
  • os.Getwd() will give you the current working directory. This is the equivalent to process.cwd() in Node. This will be wrong when you run your program from another directory.

Lastly, I'd recommend against pulling in a third-party package for this use case. Here's a package you can use:

package current

// Filename is the __filename equivalent
func Filename() (string, error) {
	_, filename, _, ok := runtime.Caller(1)
	if !ok {
		return "", errors.New("unable to get the current filename")
	}
	return filename, nil
}


// Dirname is the __dirname equivalent
func Dirname() (string, error) {
	filename, err := Filename()
	if err != nil {
		return "", err
	}
	return filepath.Dir(filename), nil
}

Note that I've adjusted runtime.Caller(1) to 1 because we want to get the directory of the package that called current.Dirname(), not the directory containing the current package.

Solution 11 - Go

// GetCurrentDir
func GetCurrentDir() string {
	p, _ := os.Getwd()
	return p
}
// GetParentDir
func GetParentDir(dirctory string) string {
	return substr(dirctory, 0, strings.LastIndex(dirctory, "/"))
}
func substr(s string, pos, length int) string {
	runes := []rune(s)
	l := pos + length
	if l > len(runes) {
		l = len(runes)
	}
	return string(runes[pos:l])
}

Solution 12 - Go

None of the answers here worked for me, at least on go version go1.16.2 darwin/amd64. This is the only thing close to the __dirname functionality in node

This was posted by goland engineer Daniil Maslov in the jetbrains forums

pasted below for easier reading:


The trick is actually very simple and is to get the current executing and add .. to the project root.

Create a new directory and file like testing_init.go with the following content:

package testing_init

import (
  "os"
  "path"
  "runtime"
)

func init() {
  _, filename, _, _ := runtime.Caller(0)
  dir := path.Join(path.Dir(filename), "..")
  err := os.Chdir(dir)
  if err != nil {
    panic(err)
  }
}

After that, just import the package into any of the test files:


package main_test

import (
  _ "project/testing_init"
)

Now you can specify paths from the project root

Solution 13 - Go

If your file is not in the main package then the above answers won't work I tried different approaches to find find the directory of the currently running file but failed.

The best possible answer is in the question itself this is how I find the current working directory of the file which is not in the main package.

_, filename, _, _ := runtime.Caller(1)
pwd := path.Dir(filename)

Solution 14 - Go

Do not use the "Answer recommended by Go Language" with runtime.Caller(0).

That works when you go build or go install a program, because you are re-compiling it.

But when you go build a program and then distribute it (copy) on your colleagues' workstations (who don't have Go, and just need the executable), the result of runtime.Caller(0) would still be the path of where you built it (from your computer).
Ie a path which would likely not exist on their own computer.

os.Args[0] or, better, os.Executable() (mentioned here) and kardianos/osext (mentioned here and here), are more reliable.

Solution 15 - Go

Gustavo Niemeyer's answer is great. But in Windows, runtime proc is mostly in another dir, like this:

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

If you use relative file path, like "/config/api.yaml", this will use your project path where your code exists.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionekannaView Question on Stackoverflow
Solution 1 - GoIntermernetView Answer on Stackoverflow
Solution 2 - GoGustavo NiemeyerView Answer on Stackoverflow
Solution 3 - GoDobrosław ŻybortView Answer on Stackoverflow
Solution 4 - GoAri SeyhunView Answer on Stackoverflow
Solution 5 - GovikydView Answer on Stackoverflow
Solution 6 - GobenyaminView Answer on Stackoverflow
Solution 7 - Gogaurav aroraView Answer on Stackoverflow
Solution 8 - GoAnother ProgView Answer on Stackoverflow
Solution 9 - GoIsaac WeingartenView Answer on Stackoverflow
Solution 10 - GoMattView Answer on Stackoverflow
Solution 11 - Gozld126126View Answer on Stackoverflow
Solution 12 - Go1mike12View Answer on Stackoverflow
Solution 13 - GoZubair HassanView Answer on Stackoverflow
Solution 14 - GoVonCView Answer on Stackoverflow
Solution 15 - GoflypapiView Answer on Stackoverflow