Làm cách nào để tạo thư mục lồng nhau bằng Mkdir trong Golang?


95

Tôi đang cố gắng tạo một tập hợp các thư mục lồng nhau từ tệp thực thi Go chẳng hạn như 'dir1 / dir2 / dir3'. Tôi đã thành công trong việc tạo một thư mục duy nhất với dòng này:

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

Tuy nhiên, tôi không biết làm thế nào để tiếp cận việc tạo một tập hợp các thư mục lồng nhau được xác định trước bên trong thư mục đó.

Câu trả lời:


176

os.Mkdirđược sử dụng để tạo một thư mục duy nhất. Để tạo đường dẫn thư mục, hãy thử sử dụng:

os.MkdirAll(folderPath, os.ModePerm)

Truy cập tài liệu

lỗi func MkdirAll (chuỗi đường dẫn, mã tệp hoán vị)

MkdirAll tạo một đường dẫn có tên thư mục, cùng với bất kỳ cha mẹ cần thiết nào và trả về nil, nếu không sẽ trả về lỗi. Các bit quyền hoán vị được sử dụng cho tất cả các thư mục mà MkdirAll tạo ra. Nếu đường dẫn đã là một thư mục, MkdirAll không làm gì cả và trả về nil.

Biên tập:

Đã cập nhật để sử dụng chính xác os.ModePermthay thế.
Để nối các đường dẫn tệp, hãy sử dụng gói path/filepathnhư được mô tả trong câu trả lời của @Chris.


@CodeWarrior: Cảm ơn bạn đã ping. Tôi đã cập nhật câu trả lời của mình và
ủng hộ

Xin cảm ơn @chris! :)
Thales P

1
Bạn có thể muốn chọn giữa 0755os.ModePerm.
updogliu

102

Bằng cách này, bạn không phải sử dụng bất kỳ con số kỳ diệu nào:

os.MkdirAll(newPath, os.ModePerm)

Ngoài ra, thay vì sử dụng + để tạo đường dẫn, bạn có thể sử dụng:

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

Ở trên sử dụng các dấu phân tách chính xác tự động trên mỗi nền tảng cho bạn.


2
Đây là câu trả lời chính xác. Đơn giản hơn nhiều và bất khả tri nền tảng.
Dan Esparza

6

Nếu vấn đề là tạo tất cả các thư mục mẹ cần thiết, bạn có thể cân nhắc sử dụng os.MkDirAll()

MkdirAll tạo một đường dẫn có tên thư mục, cùng với bất kỳ cha mẹ cần thiết nào và trả về nil, nếu không sẽ trả về lỗi.

Các path_test.go là một minh họa tốt về làm thế nào để sử dụng nó:

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

(Đảm bảo chỉ định một giá trị quyền hợp lý, như được đề cập trong câu trả lời này )


3

Một phương pháp tiện ích như sau có thể được sử dụng để giải quyết vấn đề này.

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

1

Đây là một giải pháp thay thế để đạt được điều tương tự nhưng nó tránh được tình trạng chạy đua do có hai hoạt động "kiểm tra .. và .. tạo" riêng biệt.

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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.