web-dev-qa-db-fra.com

Comment créer des répertoires imbriqués en utilisant Mkdir dans Golang?

J'essaie de créer un ensemble de répertoires imbriqués à partir d'un exécutable Go tel que 'dir1/dir2/dir3'. J'ai réussi à créer un seul répertoire avec cette ligne:

os.Mkdir("." + string(filepath.Separator) + c.Args().First(),0777);

Cependant, je ne sais pas comment aborder la création d'un ensemble de répertoires imbriqués prédéterminé à l'intérieur de ce répertoire.

54
tommymcdonald

os.Mkdir est utilisé pour créer un seul répertoire. Pour créer un chemin de dossier, essayez plutôt d'utiliser:

os.MkdirAll(folderPath, os.ModePerm);

Aller à la documentation

erreur func MkdirAll (chaîne de chemin, FileMode permanente) 

MkdirAll crée un répertoire nommé chemin, avec tous les parents nécessaires, et renvoie la valeur nil ou renvoie une erreur. Les bits d'autorisation perm sont utilisés pour tous les répertoires créés par MkdirAll. Si chemin est déjà un répertoire, MkdirAll ne fait rien et renvoie nil.

Modifier:

Mis à jour pour utiliser correctement os.ModePerm à la place.
Pour concaténer les chemins de fichiers, utilisez le package path/filepath comme décrit dans la réponse de @Chris. 

95
ANisus

De cette façon, vous ne devez utiliser aucun nombre magique:

os.MkdirAll(newPath, os.ModePerm)

De plus, plutôt que d'utiliser + pour créer des chemins, vous pouvez utiliser:

import "path/filepath"
path := filepath.Join(someRootPath, someSubPath)

Ce qui précède utilise les séparateurs appropriés automatiquement sur chaque plate-forme.

69
Chris

Si le problème est de créer tous les répertoires parents nécessaires, vous pouvez envisager d'utiliser os.MkDirAll()

MkdirAll crée un répertoire nommé chemin, ainsi que tous les parents nécessaires, et renvoie nil ou renvoie une erreur.

Le path_test.go est une bonne illustration de son utilisation:

func TestMkdirAll(t *testing.T) {
    tmpDir := TempDir()
    path := tmpDir + "/_TestMkdirAll_/dir/./dir2"
    err := MkdirAll(path, 0777)
    if err != nil {
    t.Fatalf("MkdirAll %q: %s", path, err)
    }
    defer RemoveAll(tmpDir + "/_TestMkdirAll_")
...
}

(Assurez-vous de spécifier une valeur d'autorisation raisonnable, comme indiqué dans cette réponse )

4
VonC

C'est une alternative pour atteindre le même but, mais cela évite la situation critique provoquée par deux opérations distinctes "vérifier .. et .. créer".

package main

import (
    "fmt"
    "os"
)

func main()  {
    if err := ensureDir("/test-dir"); err != nil {
        fmt.Println("Directory creation failed with error: " + err.Error())
        os.Exit(1)
    }
    // Proceed forward
}

func ensureDir(dirName string) error {

    err := os.MkdirAll(dirName, os.ModeDir)

    if err == nil || os.IsExist(err) {
        return nil
    } else {
        return err
    }
}
0

Une méthode utilitaire comme celle-ci peut être utilisée pour résoudre ce problème.

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

func ensureDir(fileName string) {
  dirName := filepath.Dir(fileName)
  if _, serr := os.Stat(dirName); serr != nil {
    merr := os.MkdirAll(dirName, os.ModePerm)
    if merr != nil {
        panic(merr)
    }
  }
}



func main() {
  _, cerr := os.Create("a/b/c/d.txt")
  if cerr != nil {
    log.Fatal("error creating a/b/c", cerr)
  }
  log.Println("created file in a sub-directory.")
}
0
skipy