web-dev-qa-db-fra.com

Comment obtenir le répertoire du fichier en cours d'exécution?

Dans nodejs j'utilise __dirname . Quel est l'équivalent de cela à Golang?

J'ai cherché sur Google et découvert cet article http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/ . Où il utilise le code ci-dessous

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

Mais est-ce la bonne façon ou la façon idiomatique de faire à Golang?

175
ekanna

Cela devrait le faire:

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)
}
175
Gustavo Niemeyer

EDIT: à compter de Go 1.8 (publié en février 2017), la méthode recommandée consiste à utiliser os.Executable :

func Executable() (string, error)

L'exécutable renvoie le nom du chemin de l'exécutable qui a démarré le processus en cours. Rien ne garantit que le chemin d'accès pointe toujours vers l'exécutable correct. Si un lien symbolique a été utilisé pour démarrer le processus, en fonction du système d'exploitation, le résultat pourrait être le lien symbolique ou le chemin indiqué. Si un résultat stable est nécessaire, path/filepath.EvalSymlinks peut vous aider.

Pour obtenir uniquement le répertoire de l'exécutable, vous pouvez utiliser path/filepath.Dir .

Exemple :

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

ANCIENNE REPONSE:

Vous devriez pouvoir utiliser os.Getwd

_func Getwd() (pwd string, err error)
_

Getwd renvoie un nom de chemin racine correspondant au répertoire actuel. Si le répertoire en cours est accessible via plusieurs chemins (en raison de liens symboliques), Getwd peut renvoyer l’un d’eux.

Par exemple:

_package main

import (
    "fmt"
    "os"
)

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

Utilisez le paquet osext

Il fournit la fonction ExecutableFolder() qui renvoie un chemin absolu au dossier où réside l'exécutable du programme en cours d'exécution (utile pour les tâches cron). C'est la plate-forme transversale.

Documentation en ligne

package main

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

func main() {
    folderPath, err := osext.ExecutableFolder()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(folderPath)
}
51
Dobrosław Żybort
filepath.Abs("./")

Abs renvoie une représentation absolue du chemin. Si le chemin n'est pas absolue, il sera associé au répertoire de travail en cours pour activer dans un chemin absolu.

Comme indiqué dans le commentaire, cela renvoie le répertoire actuellement actif.

6
Acidic

Si vous utilisez le paquet osext by kardianos et que vous avez besoin de tester localement, comme Derek Dowling a commenté:

Cela fonctionne bien jusqu’à ce que vous souhaitiez l’utiliser avec go run main.go pour développement local. Vous ne savez pas comment faire pour éviter cela sans construire un exécutable au préalable à chaque fois.

La solution à cela est de créer un utilitaire gorun.exe au lieu d’utiliser go run. L'utilitaire gorun.exe compilerait le projet à l'aide de "go build", puis l'exécuterait tout de suite après, dans le répertoire normal de votre projet.

J'avais ce problème avec d'autres compilateurs et je me suis retrouvé à faire ces utilitaires car ils ne sont pas livrés avec le compilateur ... c'est particulièrement mystérieux avec des outils comme C où vous devez compiler et lier puis exécuter (trop de travail).

Si quelqu'un aime mon idée de gorun.exe (ou elf), je le téléchargerai probablement sur github bientôt ..

Désolé, cette réponse est conçue comme un commentaire, mais je ne peux pas le comment car je n’ai pas encore une réputation assez grande.

Alternativement, "go run" pourrait être modifié (s'il ne possède pas encore cette fonctionnalité) pour avoir un paramètre tel que "go run -notemp" afin de ne pas exécuter le programme dans un répertoire temporaire (ou quelque chose de similaire). Mais je préférerais simplement taper gorun ou "gor" car il est plus court qu'un paramètre compliqué. Gorun.exe ou gor.exe devront être installés dans le même répertoire que votre compilateur go

Implémenter gorun.exe (ou gor.exe) serait trivial, comme je l'ai déjà fait avec d'autres compilateurs en seulement quelques lignes de code ... (derniers mots célèbres ;-)

2
Another Prog

si vous utilisez cette façon: 

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

vous obtiendrez le chemin/tmp lorsque vous exécuterez un programme utilisant un IDE comme GoLang car l'exécutable sera enregistré et exécuté à partir de/tmp

je pense que la meilleure façon d’obtenir le répertoire currentWorking ou "." est :

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

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

la fonction os.Getwd () retournera le répertoire de travail en cours.

1
Bit

cela suffit parfois, l'argument des sapins sera toujours le chemin du fichier paquet principal

import (
    "fmt"
    "os"
)


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

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

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

Démo complète:

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
vikyd