it-swarm.com.de

Wie erstellt man verschachtelte Verzeichnisse mit Mkdir in Golang?

Ich versuche, aus einer ausführbaren Go-Datei einen Satz verschachtelter Verzeichnisse zu erstellen, beispielsweise 'dir1/dir2/dir3'. Es ist mir gelungen, ein einzelnes Verzeichnis mit dieser Zeile zu erstellen:

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

Ich habe jedoch keine Ahnung, wie man das Erstellen einer vorgegebenen verschachtelten Gruppe von Verzeichnissen innerhalb dieses Verzeichnisses anstellt.

54
tommymcdonald

os.Mkdir wird zum Erstellen eines einzelnen Verzeichnisses verwendet. Um einen Ordnerpfad zu erstellen, verwenden Sie stattdessen Folgendes:

os.MkdirAll(folderPath, os.ModePerm);

Go-Dokumentation

func MkdirAll (Pfadzeichenfolge, zulässiger FileMode) -Fehler 

MkdirAll erstellt ein Verzeichnis mit dem Namen path und den erforderlichen übergeordneten Elementen und gibt nil zurück oder gibt einen Fehler zurück. Die Berechtigungsbits perm werden für alle Verzeichnisse verwendet, die MkdirAll erstellt. Wenn path bereits ein Verzeichnis ist, führt MkdirAll nichts aus und gibt nil zurück.

Bearbeiten:

Aktualisiert, um stattdessen os.ModePerm korrekt zu verwenden.
Verwenden Sie zum Verketten von Dateipfaden das Paket path/filepath wie in der Antwort von @Chris beschrieben. 

95
ANisus

Auf diese Weise müssen Sie keine magischen Zahlen verwenden:

os.MkdirAll(newPath, os.ModePerm)

Statt mit + Pfade zu erstellen, können Sie auch Folgendes verwenden:

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

Das Obige verwendet automatisch die korrekten Trennzeichen auf jeder Plattform für Sie.

69
Chris

Wenn das Problem darin besteht, alle erforderlichen übergeordneten Verzeichnisse zu erstellen, können Sie die Verwendung von os.MkDirAll() in Betracht ziehen.

MkdirAll erstellt ein Verzeichnis mit dem Namen path und den erforderlichen übergeordneten Elementen und gibt nil zurück oder gibt einen Fehler zurück.

Das path_test.go ist eine gute Illustration, wie man es benutzt:

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

(Stellen Sie sicher, dass Sie einen sinnvollen Berechtigungswert angeben, wie in diese Antwort erwähnt).

4
VonC

Dies ist eine Alternative, um dasselbe zu erreichen, vermeidet jedoch die Racebedingung, die durch zwei unterschiedliche "check ..and .. create" -Operationen verursacht wird.

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

Eine Dienstmethode wie die folgende kann verwendet werden, um dieses Problem zu lösen.

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