我希望func FolderExists(path string) bool
能够判断文件夹是否存在且可写。我来到这里:
func FolderExists(path string) bool {
info, err := os.Stat(path)
return os.IsExist(err) && info.Mode().IsDir() && info.Mode().???
}
如何判断此文件夹是否可写?我不能简单地检查filemode权限(例如0200用于用户写入权限),因为那时我必须检查文件的所有者。在Go中有直接的方法吗?
对于那些拥有UNIX背景的人来说,寻找相当于非常简单的东西:
if [ -d "$n" && -w "$n" ] ; then ... fi
答案 0 :(得分:8)
如果您正在为Unix-y操作系统编写代码,则可以将unix.Access(path string, mode uint32) error
与常量unix.W_OK
一起用作mode
。
正如kostix所说,您仍然需要在访问目录时检查错误(例如,当您创建或删除文件时)。您的检查可能已删除该目录,或者权限可能已更改,或者您可能会收到完全无关的错误。
(感谢用户fxxn指出自2013年原始答案以来情况有所改善,即使用syscall.Access
并从W_OK
中提取unistd.h
常量。)< / p>
这是检查存在和访问的代码,它可以在Linux上获得预期的结果:
package main
import (
"fmt"
"golang.org/x/sys/unix"
)
func writable(path string) bool {
return unix.Access(path, unix.W_OK) == nil
}
func main() {
fmt.Println("/etc writable?", writable("/etc"))
fmt.Println("/tmp writable?", writable("/tmp"))
}
答案 1 :(得分:2)
没有与平台无关的方法来实现这一点,因为在Windows上无法检查用户是否无法创建目录。因此,我们将针对Windows和非Windows系统以不同方式实现它,然后使用Golang的build constraints根据操作系统有条件地编译文件。
在目录file-perm下创建3个.go文件,如图所示 -
file-perm /
file-perm.go
is-writable.go
is-writable_windows.go
文件:file-perm.go
package main
import (
"fmt"
)
func main() {
path := "/tmp/xyz"
fmt.Println(IsWritable(path))
}
档案:is-writable.go
这构建在除Windows之外的所有平台上,因为Windows上没有syscall.Stat_t。请注意,构建约束 // + build!windows
后需要有一个空行// +build !windows
package main
import (
"fmt"
"os"
"syscall"
)
func IsWritable(path string) (isWritable bool, err error) {
isWritable = false
info, err := os.Stat(path)
if err != nil {
fmt.Println("Path doesn't exist")
return
}
err = nil
if !info.IsDir() {
fmt.Println("Path isn't a directory")
return
}
// Check if the user bit is enabled in file permission
if info.Mode().Perm() & (1 << (uint(7))) == 0 {
fmt.Println("Write permission bit is not set on this file for user")
return
}
var stat syscall.Stat_t
if err = syscall.Stat(path, &stat); err != nil {
fmt.Println("Unable to get stat")
return
}
err = nil
if uint32(os.Geteuid()) != stat.Uid {
isWritable = false
fmt.Println("User doesn't have permission to write to this directory")
return
}
isWritable = true
return
}
档案:is-writable_windows.go
由于文件名中的 _windows.go 后缀,此文件仅在Windows上构建。有关详细信息,请参阅https://golang.org/pkg/go/build/
package main
import (
"fmt"
"os"
)
func IsWritable(path string) (isWritable bool, err error) {
isWritable = false
info, err := os.Stat(path)
if err != nil {
fmt.Println("Path doesn't exist")
return
}
err = nil
if !info.IsDir() {
fmt.Println("Path isn't a directory")
return
}
// Check if the user bit is enabled in file permission
if info.Mode().Perm()&(1<<(uint(7))) == 0 {
fmt.Println("Write permission bit is not set on this file for user")
return
}
isWritable = true
return
}
现在,你必须在file-perm目录中使用 go build然后运行 可执行文件。请注意,它不适用于go run。
答案 2 :(得分:0)
我的回答不会直接回答你的问题,但仍然......
简而言之:不要那样做(除非你写的东西是嵌入的)。说明:文件系统是完全并发的,因此它们本身就是竞争条件的主题。简单来说,一个序列
不能在现实世界中工作,因为文件完全能够在(1)和(2)之间消失,因为其他一些进程会删除它。
因此,编写上述序列的唯一真正方法是删除(1)并准备处理(2)中的文件打开错误。
回到你的问题,唯一合理的方法是尝试在目标目录中创建一个文件,并准备好处理由于目录不可写而导致的错误。此外,Go的错误处理方法专门针对此类(现实世界)情况而定制。