Bagaimana cara membuat direktori bersarang menggunakan Mkdir di Golang?

97

Saya mencoba membuat satu set direktori bersarang dari Go yang dapat dieksekusi seperti 'dir1 / dir2 / dir3'. Saya telah berhasil membuat satu direktori dengan baris ini:

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

Namun, saya tidak tahu bagaimana melakukan pendekatan untuk membuat kumpulan direktori bersarang yang telah ditentukan sebelumnya di dalam direktori itu.

tommymcdonald
sumber

Jawaban:

182

os.Mkdirdigunakan untuk membuat satu direktori. Untuk membuat jalur folder, coba gunakan:

os.MkdirAll(folderPath, os.ModePerm)

Pergi dokumentasi

func MkdirAll (jalur string, perm FileMode) kesalahan

MkdirAll membuat direktori bernama path, bersama dengan orang tua yang diperlukan, dan mengembalikan nihil, atau mengembalikan kesalahan. Bit izin perm digunakan untuk semua direktori yang dibuat MkdirAll. Jika path sudah menjadi direktori, MkdirAll tidak melakukan apa-apa dan mengembalikan nihil.

Edit:

Diperbarui untuk digunakan dengan benar os.ModePerm.
Untuk penggabungan jalur file, gunakan paket path/filepathseperti yang dijelaskan dalam jawaban @Chris.

ANisus
sumber
@ CodeWarrior: Terima kasih atas pingnya. Saya memperbarui jawaban saya dan memberi suara positif pada Chris
ANisus
Terima kasih @chris! :)
Thales P
1
Anda mungkin ingin memilih antara 0755dan os.ModePerm.
updogliu
103

Dengan cara ini Anda tidak perlu menggunakan angka ajaib:

os.MkdirAll(newPath, os.ModePerm)

Selain itu, daripada menggunakan + untuk membuat jalur, Anda dapat menggunakan:

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

Di atas menggunakan pemisah yang benar secara otomatis di setiap platform untuk Anda.

Chris
sumber
3
Ini jawaban yang benar. Jauh lebih sederhana dan platform agnostik.
Dan Esparza
6

Jika masalahnya adalah membuat semua direktori induk yang diperlukan, Anda dapat mempertimbangkan untuk menggunakan os.MkDirAll()

MkdirAll membuat direktori bernama jalur, bersama dengan orang tua yang diperlukan, dan mengembalikan nihil, atau mengembalikan kesalahan.

The path_test.go adalah ilustrasi yang baik tentang cara menggunakannya:

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

(Pastikan untuk menentukan nilai izin yang masuk akal, seperti yang disebutkan dalam jawaban ini )

VonC
sumber
3

Metode utilitas seperti berikut dapat digunakan untuk menyelesaikan masalah ini.

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.")
}
cakep
sumber
1

Ini adalah salah satu alternatif untuk mencapai hal yang sama tetapi menghindari kondisi balapan yang disebabkan oleh dua operasi "periksa .. dan .. buat" yang berbeda.

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
    }
}
pr-sobat
sumber