【问题标题】:mkdir if not exists using golang如果 mkdir 不存在,则使用 golang
【发布时间】:2016-10-22 07:13:38
【问题描述】:

我正在学习 golang(初学者),我一直在 google 和 stackoverflow 上搜索,但我找不到答案,如果已经问过,请原谅,但是如果 golang 中不存在,我该如何 mkdir。

例如,在节点中,我将 fs-extra 与函数 ensureDirSync 一起使用(当然,如果不考虑阻塞)

fs.ensureDir("./public");

【问题讨论】:

    标签: go directory path filepath mkdir


    【解决方案1】:

    好的,感谢question/answer

    import(
        "os"
        "path/filepath"
    )
    
    newpath := filepath.Join(".", "public")
    err := os.MkdirAll(newpath, os.ModePerm)
    // TODO: handle error
    

    MkdirAll 的相关 Go 文档:

    MkdirAll 创建一个名为 path 的目录, 连同任何必要的父母,并返回零, 否则返回错误。

    ...

    如果 path 已经是一个目录,MkdirAll 什么都不做 并返回 nil。

    【讨论】:

    • 这是最好的答案,并且正在使用标准库。这在与 os.Create 一起使用时特别有用,您可能还需要在其中创建子目录(在文件的完整路径上使用 filepath.Dir("path/to/file") 在我看来是一个不错的方法。
    • 您可能想要检查 MkdirAll 调用上的任何错误响应,例如:` if err := os.MkdirAll("/somepath/", os.ModeDir); err != nil { fmt.Println("无法创建隐藏目录。") } `
    【解决方案2】:

    我遇到了两种方式:

    1. 检查目录是否存在,如果不存在则创建:

      if _, err := os.Stat(path); os.IsNotExist(err) {
          err := os.Mkdir(path, mode)
          // TODO: handle error
      }
      

    但是,这很容易受到竞争条件的影响:路径可能由其他人在 os.Stat 调用和 os.Mkdir 调用之间创建。

    1. 尝试创建目录并忽略任何问题(不建议忽略错误):

      _ = os.Mkdir(path, mode)
      

    【讨论】:

    • 如果有人想知道变量 mode 是什么,请参阅:golang.org/pkg/os/#FileMode。您可能希望使用 os.ModeDir 作为其值。
    • 对于那些想知道mode的人,如果您希望能够从同一程序写入该目录,可以使用os.Mkdir("dirname", 0700),请参阅this了解更多详细信息。跨度>
    • 为什么我们在执行 os.Mkdir() 时会忽略任何问题?
    • 在os.ModeDir模式下创建目录存储文件时。新目录没有足够的权限。我发现只有os.ModePerm 为我工作。相当于0777 或drwxr-xr-x。我认为权限可能会低一些,但0666 没有做到这一点。
    • 如果其他人在您检查是否存在然后创建目录之间创建目录,选项 1 会不会受到竞争条件的影响?
    【解决方案3】:

    您可以使用os.Stat 检查给定路径是否存在。
    如果没有,您可以使用os.Mkdir 创建它。

    【讨论】:

      【解决方案4】:

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

      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.Mkdir(dirName, os.ModeDir)
          if err == nil {
              return nil
          }
          if os.IsExist(err) {
              // check that the existing path is a directory
              info, err := os.Stat(dirName)
              if err != nil {
                  return err
              }
              if !info.IsDir() {
                  return errors.New("path exists but is not a directory")
              }
              return nil
          }
          return err  
      }
      

      【讨论】:

      • 虽然您的代码可能会提供问题的答案,但请在其周围添加上下文,以便其他人了解它的作用以及它存在的原因。
      • 这个答案部分不正确。 os.IsExist(err) 签入ensureDir 是不够的:现有路径不一定是目录。所以ensureDir 将返回一个 nil 错误,但最终路径中的项目可能不是目录(例如,它可能是一个 reguar 文件)。
      • 我已经在对此答案的编辑中解决了我之前评论中描述的问题。
      【解决方案5】:

      所以我发现对我有用的是:

      //Get the base file dir
      path, err := os.Getwd()
      if err != nil {
          log.Println("error msg", err)
      }
      
      //Create output path
      outPath:= filepath.Join(path, "output")
      
      //Create dir output using above code
      if _, err := os.Stat(outPath); os.IsNotExist(err) {
          os.Mkdir(outPath, 0755)
      }
      

      我喜欢它的便携性。

      【讨论】:

        【解决方案6】:

        或者您可以尝试创建文件并检查返回的错误是否不是“文件存在”错误

        if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
            log.Fatal(err)
        }
        

        【讨论】:

        • 这个答案部分不正确。特别是!os.IsExist(err) 检查不正确。现有路径不一定是目录。所以最终代码将继续前进(即log.Fatal不会被执行),但path可能不是一个目录(它可能是一个reguar文件,例如)。
        猜你喜欢
        • 2016-10-15
        • 2013-09-08
        • 2020-07-22
        • 2021-04-19
        • 2014-07-20
        • 2015-04-11
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        相关资源
        最近更新 更多