如何在Go中检查文件夹是否为空?我可以这样检查:
files, err := ioutil.ReadDir(*folderName)
if err != nil {
return nil, err
}
// here check len of files
但在我看来,似乎应该有更加优雅的解决方案。
无论一个目录是否为空,都不会像名字、创建时间或大小(针对文件)这样作为文件系统级别的属性来存储。
话虽如此,你不能仅通过查询 os.FileInfo
来获取这些信息。最简单的方式是查询目录的子项(内容)。
ioutil.ReadDir()
是相当糟糕的选择,因为它首先读取指定目录所有内容,然后按名称排序,并返回切片。最快的方法是像 Dave C 提到的那样:使用 File.Readdir()
或者(更好地),File.Readdirnames()
查询目录的子项。
File.Readdir()
和 File.Readdirnames()
都需要一个参数,用于限制返回的值数。只查询一个子项就足够了。因为 Readdirnames()
只返回名称,所以它更快,因为不需要进一步调用获取(和构造)FileInfo
结构。
请注意,如果目录为空,则会返回 io.EOF
作为错误(而不是空或 nil
切片),因此我们甚至不需要返回的名称切片。
最终代码可能如下所示:
func IsEmpty(name string) (bool, error) {
f, err := os.Open(name)
if err != nil {
return false, err
}
defer f.Close()
_, err = f.Readdirnames(1) // Or f.Readdir(1)
if err == io.EOF {
return true, nil
}
return false, err // Either not empty or error, suits both cases
}
File.Readdirnames()
的实现似乎基于 File.Readdir()
。 - mat007File.Readdirnames()
,因为它的实现只读取名称,而File.Readdir
还会读取每个找到的文件的统计信息。请参见https://go.dev/src/os/dir_windows.go第40行。 - Mikhail Kopylov
f.Readdir(1)
只查看第一个目录条目(如果需要跳过“.”和“..”,则为3)(如果可能有许多目录条目,则很有帮助)。但要注意,你只能知道“目录曾经为空”,在你检查时它可能已经有新文件了。这可能是没有“简单”检查存在的原因之一;因为它相当无用。[例如,这就是为什么像rmdir
这样的东西不会检查,它们只是尝试删除目录并处理/报告ENOTEMPTY
,因为那是原子操作。] - Dave Cf.Readdirnames(1)
(或3)会更好一些。 - Dave C