我想删除文件的所有路径组件,但不包括整个基本目录。
实施例: /总/ BASEDIR / A / B / C /文件
我想删除"文件"然后删除" c"," b"然后" a"如果可能(目录不为空)。我不想取消联系" basedir"或"整体"。
filepath.HasPrefix似乎是一个不错的选择,但它显然已被弃用:https://golang.org/pkg/path/filepath/#HasPrefix
我现在拥有的是:
p := THEPATH
// attempt to remove file and all parent directories up to the basedir
// FIXME: HasPrefix is apparently bad.. a better idea?
for filepath.HasPrefix(p, baseDir) {
err := os.Remove(p)
if err != nil {
break
}
// climb up one
p = filepath.Dir(p)
}
寻找一种适用于所有Go支持平台的简洁可靠的方法。
答案 0 :(得分:1)
恕我直言,如果您想支持golang
支持的所有平台,则路径处理相当复杂。贝娄是我迄今为止实施的解决方案(可能不是最简单的解决方案)。注意:
os.Remove
os.SameFile
用于测试两个文件/目录是否相等,而不是基于字符串的路径比较。 visitedPaths
切片。然后,如果没有发生错误,则对每个候选路径执行action
。package pathwalker
import (
"os"
"path/filepath"
"strings"
)
type PathAction func(PathInfo) error
type PathInfo struct {
FileInfo os.FileInfo
FullPath string
}
type PathWalker struct {
pathName string
basePath string
visitedPaths []PathInfo
lastFi os.FileInfo
}
//NewPathWalker creates PathWalker instance
func NewPathWalker(pathName, basePath string) *PathWalker {
return &PathWalker{
pathName: pathName,
basePath: basePath,
}
}
func (w *PathWalker) visit() (bool, error) {
//Make sure path ends with separator
basePath := filepath.Clean(w.basePath + string(filepath.Separator))
baseInfo, err := os.Lstat(basePath)
if err != nil {
return false, err
}
//clean path name
fi, err := os.Lstat(w.pathName)
if err != nil {
return false, err
} else if fi.IsDir() {
//When pathname is a directory, remove latest separator
sep := string(filepath.Separator)
cleanPath := filepath.Clean(w.pathName + sep)
w.pathName = strings.TrimRight(cleanPath, sep)
} else {
w.pathName = filepath.Clean(w.pathName)
}
return w.doVisit(w.pathName, baseInfo)
}
//visit path recursively
func (w *PathWalker) doVisit(pathName string, baseInfo os.FileInfo) (bool, error) {
//Get file info
fi, err := os.Lstat(pathName)
if err != nil {
return false, err
}
//Stop when basePath equal to pathName
if os.SameFile(fi, baseInfo) {
return true, nil
}
//Top directory reached, but does not match baseInfo
if w.lastFi != nil && os.SameFile(w.lastFi, fi) {
return false, nil
}
w.lastFi = fi
//Append to visited path list
w.visitedPaths = append(w.visitedPaths, PathInfo{fi, pathName})
//Move to upper path
up := filepath.Dir(pathName)
if up == "." {
return false, nil
}
//Visit upper directory
return w.doVisit(up, baseInfo)
}
//Walk perform action then return number of proceed paths and error
func (w *PathWalker) Walk(act PathAction) (int, error) {
n := 0
ok, err := w.visit()
if err != nil {
return 0, err
} else if ok && act != nil {
for _, pi := range w.visitedPaths {
err := act(pi)
if err != nil {
return n, err
}
n++
}
}
return n, nil
}
//VisitedPaths return list of visited paths
func (w *PathWalker) VisitedPaths() []PathInfo {
return w.visitedPaths
}
然后,如果要删除basePath
下的文件和父目录,可以执行以下操作:
func remove(pathName, basePath string) {
act := func(p pathwalker.PathInfo) error {
if p.FileInfo.IsDir() {
fmt.Printf(" Removing directory=%s\n", p.FullPath)
return os.Remove(p.FullPath)
}
fmt.Printf(" Removing file=%s\n", p.FullPath)
return os.Remove(p.FullPath)
}
pw := pathwalker.NewPathWalker(pathName, basePath)
n, err := pw.Walk(act)
fmt.Printf("Removed: %d/%d, err=%v\n", n, len(pw.VisitedPaths()), err)
}
如果您只想测试路径是否在另一条路径内,您可以执行以下操作:
n, err := pathwalker.NewPathWalker(fileName, basePath).Walk(nil)
if n > 0 && err != nil {
//is inside another path
}