如何在Golang中使用Mkdir创建嵌套目录?

huangapple go评论77阅读模式
英文:

How to create nested directories using Mkdir in Golang?

问题

我正在尝试从一个Go可执行文件中创建一组嵌套的目录,例如'dir1/dir2/dir3'。我已经成功地用以下代码创建了一个单独的目录:

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

然而,我不知道如何在该目录中创建预定的嵌套目录集合。

英文:

I am trying to create a set of nested directories from a Go executable such as 'dir1/dir2/dir3'. I have succeeded in creating a single directory with this line:

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

However, I have no idea how to approach creating a predetermined nested set of directories inside of that directory.

答案1

得分: 263

os.Mkdir用于创建单个目录。如果要创建文件夹路径,请尝试使用以下代码:

os.MkdirAll(folderPath, os.ModePerm)

Go文档

func MkdirAll(path string, perm FileMode) error

MkdirAll创建一个名为path的目录,以及所有必要的父目录,并返回nil,否则返回一个错误。权限位perm用于MkdirAll创建的所有目录。如果path已经是一个目录,则MkdirAll不执行任何操作并返回nil。

编辑:

已更新为正确使用os.ModePerm
要连接文件路径,请使用path/filepath包,如@Chris的答案所述。

英文:

os.Mkdir is used to create a single directory. To create a folder path, instead try using:

os.MkdirAll(folderPath, os.ModePerm)

Go documentation
>func MkdirAll(path string, perm FileMode) error
>
MkdirAll creates a directory named path, along with any necessary parents, and returns nil, or else returns an error. The permission bits perm are used for all directories that MkdirAll creates. If path is already a directory, MkdirAll does nothing and returns nil.

Edit:

Updated to correctly use os.ModePerm instead.
For concatenation of file paths, use package path/filepath as described in @Chris' answer.

答案2

得分: 127

这样你就不需要使用任何魔法数字了:

os.MkdirAll(newPath, os.ModePerm)

另外,你可以使用以下方法来创建路径,而不是使用 + :

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

以上代码会自动在每个平台上使用正确的分隔符。

英文:

This way you don't have to use any magic numbers:

os.MkdirAll(newPath, os.ModePerm)

Also, rather than using + to create paths, you can use:

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

The above uses the correct separators automatically on each platform for you.

答案3

得分: 9

如果问题是创建所有必要的父目录,你可以考虑使用os.MkDirAll()函数。

MkdirAll函数会创建一个名为path的目录,以及所有必要的父目录,并返回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_")
...
}

(请确保指定一个合理的权限值,如此答案中所提到的)

英文:

If the issue is to create all the necessary parent directories, you could consider using os.MkDirAll()

> MkdirAll creates a directory named path, along with any necessary parents, and returns nil, or else returns an error.

The path_test.go is a good illustration on how to use it:

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

(Make sure to specify a sensible permission value, as mentioned in this answer)

答案4

得分: 8

可以使用以下类似的实用方法来解决这个问题。

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("创建 a/b/c 时出错", cerr)
  }
  log.Println("在子目录中创建文件。")
}

这段代码是一个示例,它定义了一个名为ensureDir的函数,用于确保目录存在。在main函数中,它首先调用ensureDir函数来创建目录"a/b/c",然后使用os.Create函数创建文件"d.txt"。如果创建目录或文件时出现错误,将会记录错误信息。最后,它会打印一条消息表示成功创建了一个子目录中的文件。

英文:

An utility method like the following can be used to solve this.

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

答案5

得分: 8

这是一种实现相同目的的替代方法,它避免了由于具有两个不同的“检查...并...创建”操作而引起的竞态条件。

package main

import (
    "fmt"
    "os"
)

func main()  {
    if err := ensureDir("/test-dir"); err != nil {
        fmt.Println("目录创建失败,错误信息:" + err.Error())
        os.Exit(1)
    }
    // 继续执行
}

func ensureDir(dirName string) error {

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

    if err == nil || os.IsExist(err) {
        return nil
    } else {
        return err
    }
}
英文:

This is one alternative for achieving the same but it avoids race condition caused by having two distinct "check ..and.. create" operations.

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
    }
}

huangapple
  • 本文由 发表于 2015年2月11日 15:15:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/28448543.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定