Подтвердить что ты не робот

Как создать вложенные каталоги с помощью Mkdir в Golang?

Я пытаюсь создать набор вложенных каталогов из исполняемого файла Go, такого как 'dir1/dir2/dir3'. Мне удалось создать один каталог с этой строкой:

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

Однако я понятия не имею, как подойти к созданию заранее определенного вложенного набора каталогов внутри этого каталога.

4b9b3361

Ответ 1

os.Mkdir используется для создания одного каталога. Чтобы создать путь к папке, попробуйте использовать:

os.MkdirAll(folderPath, os.ModePerm)

Перейти документация

func MkdirAll (строка пути, пермский FileMode) ошибка

MkdirAll создает каталог с именем path вместе со всеми необходимыми родителями и возвращает nil, либо возвращает ошибку. Биты разрешений perm используются для всех каталогов, которые создает MkdirAll. Если путь уже является каталогом, MkdirAll ничего не делает и возвращает nil.

Редактировать:

Обновлен для правильного использования os.ModePerm.
Для объединения путей к файлам используйте path/filepath к файлу, как описано в ответе @Chris.

Ответ 2

Таким образом, вам не нужно использовать магические числа:

os.MkdirAll(newPath, os.ModePerm)

Кроме того, вместо использования + для создания путей вы можете использовать:

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

Вышеупомянутые правила используют для каждой платформы правильные разделители на каждой платформе.

Ответ 3

Если проблема заключается в создании всех необходимых родительских каталогов, вы можете рассмотреть возможность использования 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_")
...
}

(Не забудьте указать разумное значение разрешения, как указано в этом ответе)

Ответ 4

Для решения этой проблемы можно использовать такой метод, как приведенный ниже.

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

Это одна альтернатива для достижения того же самого, но она позволяет избежать состояния гонки, вызванного наличием двух разных операций "проверить.. и.. создать".

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