จะสร้างไดเรกทอรีที่ซ้อนกันโดยใช้ Mkdir ใน Golang ได้อย่างไร


97

ฉันกำลังพยายามสร้างชุดของไดเร็กทอรีที่ซ้อนกันจากโปรแกรม Go เช่น 'dir1 / dir2 / dir3' ฉันประสบความสำเร็จในการสร้างไดเรกทอรีเดียวด้วยบรรทัดนี้:

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

อย่างไรก็ตามฉันไม่รู้ว่าจะสร้างชุดไดเร็กทอรีซ้อนที่กำหนดไว้ล่วงหน้าภายในไดเร็กทอรีนั้นอย่างไร

คำตอบ:


182

os.Mkdirใช้เพื่อสร้างไดเร็กทอรีเดียว ในการสร้างเส้นทางโฟลเดอร์ให้ลองใช้:

os.MkdirAll(folderPath, os.ModePerm)

ไปที่เอกสาร

func MkdirAll (path string, perm FileMode) เกิดข้อผิดพลาด

MkdirAll สร้างไดเร็กทอรีชื่อพา ธ พร้อมกับพาเรนต์ที่จำเป็นและส่งคืนค่า nil หรือส่งกลับข้อผิดพลาด อนุญาตบิตการอนุญาตใช้สำหรับไดเร็กทอรีทั้งหมดที่ MkdirAll สร้างขึ้น ถ้าพา ธ เป็นไดเร็กทอรีอยู่แล้ว MkdirAll จะไม่ทำอะไรเลยและส่งกลับค่า nil

แก้ไข:

ปรับปรุงให้ถูกต้องใช้os.ModePermแทน
สำหรับการต่อเส้นทางไฟล์ให้ใช้แพ็คเกจpath/filepathตามที่อธิบายไว้ในคำตอบของ @Chris


@CodeWarrior: ขอบคุณสำหรับ ping ฉันอัปเดตคำตอบและโหวตให้ Chris
ANisus

ขอบคุณ @chris! :)
Thales P

1
คุณอาจต้องการที่จะเลือกระหว่างและ0755 os.ModePerm
updogliu

103

วิธีนี้คุณไม่ต้องใช้ตัวเลขวิเศษใด ๆ :

os.MkdirAll(newPath, os.ModePerm)

นอกจากนี้แทนที่จะใช้ + เพื่อสร้างเส้นทางคุณสามารถใช้:

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

ข้างต้นใช้ตัวคั่นที่ถูกต้องโดยอัตโนมัติในแต่ละแพลตฟอร์มสำหรับคุณ


3
นี่คือคำตอบที่ถูกต้อง ง่ายกว่ามากและไม่เชื่อเรื่องพระเจ้าบนแพลตฟอร์ม
Dan Esparza

6

หากปัญหาคือการสร้างไดเร็กทอรีพาเรนต์ที่จำเป็นทั้งหมดคุณสามารถพิจารณาใช้ os.MkDirAll()

MkdirAll สร้างไดเร็กทอรีชื่อพา ธ พร้อมกับพาเรนต์ที่จำเป็นและส่งคืนค่า nil มิฉะนั้นจะส่งกลับข้อผิดพลาด

path_test.goเป็นภาพที่ดีเกี่ยวกับวิธีการใช้:

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

(อย่าลืมระบุค่าสิทธิ์ที่เหมาะสมตามที่กล่าวไว้ในคำตอบนี้ )


3

สามารถใช้วิธีการยูทิลิตี้ดังต่อไปนี้เพื่อแก้ปัญหานี้

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

นี่เป็นทางเลือกหนึ่งในการบรรลุเป้าหมายเดียวกัน แต่หลีกเลี่ยงสภาพการแข่งขันที่เกิดจากการมีการดำเนินการ "ตรวจสอบ .. และ .. สร้าง" ที่แตกต่างกันสองรายการ

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
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.