我是Go的新手,似乎无法找到一种删除目录中所有内容的方法。

我试过了:

1
2
os.RemoveAll("/tmp/*")
os.Remove("/tmp/*")

但获取remove *: no such file or directoryinvalid argument

当然,如果您这样做:

1
os.RemoveAll("/tmp/")

它也会删除tmp目录。 这不是我想要的。

  • 您可以使用shell命令来执行ofc并调用os.Exec。
  • @ 0x434D53:Shell命令取决于操作系统和Shell。 使用Go软件包os OS和独立于Shell的功能来实现可移植性。 例如,我在Linux和Windows上测试了我的Go解决方案。
  • 他们是Ofc。 只是一个可能适合他用例的建议。 有一个原因我没有写它作为答案。

这可能是一个愚蠢的答案,但为什么不简单地做呢?

1
2
os.RemoveAll("/tmp/")
os.MkdirAll("/tmp/",FileMode)
  • 我不确定,当提出这个问题时它不存在,或者它做了意外的事情。
  • 当他谈论removeall时,它很可能存在,所以它可能会做一些意想不到的事情,但是我想知道在我经常使用此方法时会发生什么
  • @Lomithrani RemoveAll说它在第一次遇到错误时退出。单独删除每个文件将使您可以删除更多文件,以防可能出现多个错误。这就是我阅读文档后能想到的全部内容。
  • 哦,等等,我想我们正在尝试删除目录的内容,而不是目录本身。正如我在问题底部所说的那样,removeAll也会删除父目录。再次创建目录可以使用,但需要匹配在其上设置的当前权限。
  • 如果您无权删除tmp,则此方法将无效。

编写一个简单的RemoveContents函数。 例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package main

import (
   "fmt"
   "os"
   "path/filepath"
   "strings"
)

func RemoveContents(dir string) error {
    d, err := os.Open(dir)
    if err != nil {
        return err
    }
    defer d.Close()
    names, err := d.Readdirnames(-1)
    if err != nil {
        return err
    }
    for _, name := range names {
        err = os.RemoveAll(filepath.Join(dir, name))
        if err != nil {
            return err
        }
    }
    return nil
}

func main() {
    dir := strings.TrimSuffix(filepath.Base(os.Args[0]), filepath.Ext(os.Args[0]))
    dir = filepath.Join(os.TempDir(), dir)
    dirs := filepath.Join(dir, `tmpdir`)
    err := os.MkdirAll(dirs, 0777)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    file := filepath.Join(dir, `tmpfile`)
    f, err := os.Create(file)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    f.Close()
    file = filepath.Join(dirs, `tmpfile`)
    f, err = os.Create(file)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    f.Close()

    err = RemoveContents(dir)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}
  • 谢谢,我实际上做了一些类似的事情,但是使用ioutil.ReadDir来保存打开目录。谢谢
  • @mattl:那不好。对于包os," Readdirnames从目录中读取并返回一部分名称。"对于包ioutil," ReadDir读取以目录名命名的目录,并返回已排序目录条目的列表。"从os切换到ioutil,您添加了不必要的名称列表:func ReadDirsort.Sort(byName(list))

只需使用ioutil.ReadDir即可获取os.FileInfo类型的切片,然后使用os.RemoveAll遍历并删除每个子项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
   "io/ioutil"
   "os"
   "path"
)

func main() {
    dir, err := ioutil.ReadDir("/tmp")
    for _, d := range dir {
        os.RemoveAll(path.Join([]string{"tmp", d.Name()}...))
    }
}

这样,您将仅删除所有子项,而不删除父/tmp文件夹本身。

我以前已经使用过这种模式很多次(例如测试日志等)。


1
2
3
4
5
6
7
8
9
10
11
12
13
func RemoveContents(dir string) error {
    files, err := filepath.Glob(filepath.Join(dir,"*"))
    if err != nil {
        return err
    }
    for _, file := range files {
        err = os.RemoveAll(file)
        if err != nil {
            return err
        }
    }
    return nil
}
  • 不好。模式*与隐藏文件不匹配(名称以点开头,例如.config.yaml)。 OP要求删除目录的所有内容。