web-dev-qa-db-ja.com

GolangのMkdirを使用してネストされたディレクトリを作成する方法は?

「dir1/dir2/dir3」などのGo実行可能ファイルからネストされたディレクトリのセットを作成しようとしています。私はこの行で単一のディレクトリを作成することに成功しました:

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

ただし、そのディレクトリ内にあらかじめ定義されたネストされたディレクトリセットを作成する方法についてはわかりません。

68
tommymcdonald

os.Mkdirは、単一のディレクトリを作成するために使用されます。フォルダーパスを作成するには、代わりに以下を使用してみてください。

os.MkdirAll(folderPath, os.ModePerm)

ドキュメントを表示

func MkdirAll(パス文字列、perm FileMode)エラー

MkdirAllは、必要な親とともにpathという名前のディレクトリを作成し、nilを返すか、エラーを返します。許可ビットpermは、MkdirAllが作成するすべてのディレクトリに使用されます。 pathがすでにディレクトリの場合、MkdirAllは何もせずにnilを返します。

編集:

代わりにos.ModePermを正しく使用するように更新されました。
ファイルパスを連結するには、@ Chrisの回答で説明されているように、パッケージpath/filepathを使用します。

125
ANisus

このように、マジックナンバーを使用する必要はありません。

os.MkdirAll(newPath, os.ModePerm)

また、+を使用してパスを作成する代わりに、次を使用できます。

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

上記では、各プラットフォームで適切なセパレータが自動的に使用されます。

80
Chris

問題がすべての必要な親ディレクトリを作成することである場合、 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_")
...
}

this answer で述べたように、適切な許可値を指定してください)

4
VonC

これを解決するには、次のようなユーティリティメソッドを使用できます。

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

これは、同じことを達成するための1つの代替手段ですが、2つの別個の「check ..and .. create」操作が原因で発生する競合状態を回避します。

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