假设我们有两条路径:
c:\foo\bar\baz
和c:\foo\bar
是否有任何包/方法可以帮助我确定一个是否是另一个的子目录?我正在寻找一个跨平台的选择。
答案 0 :(得分:9)
您可以尝试使用path.filepath.Rel():
func Rel(basepath, targpath string) (string, error)
Rel
返回一个相对路径,该路径在与targpath
连接时带有插入分隔符,在词汇上等效于basepath
。
也就是说,Join(basepath, Rel(basepath, targpath))
相当于targpath
本身
这意味着Rel("c:\foo\bar", "c:\foo\bar\baz")
应为baz
,这意味着c:\foo\bar\baz
中完全包含子路径,并且没有任何“../
”。
这同样适用于unix路径。
这会使c:\foo\bar\baz
成为c:\foo\bar
。
答案 1 :(得分:1)
我还没有找到适用于所有类型路径的可靠解决方案,但是最好的方法是按照VonC的建议使用filepath.Rel
。
如果两个文件路径都是绝对路径或相对路径(不允许混合),则可以使用,并且可以在Windows和Linux上使用:
func SubElem(parent, sub string) (bool, error) {
up := ".." + string(os.PathSeparator)
// path-comparisons using filepath.Abs don't work reliably according to docs (no unique representation).
rel, err := filepath.Rel(parent, sub)
if err != nil {
return false, err
}
if !strings.HasPrefix(rel, up) && rel != ".." {
return true, nil
}
return false, nil
}
以驱动器号开头的绝对Windows路径将需要进行额外检查。
答案 2 :(得分:0)
您可以使用函数path.filepath.Match()
匹配报告名称是否与外壳文件名称模式匹配。
例如:
pattern := "C:\foo\bar" + string(filepath.Separator) + "*"
matched, err := filepath.Match(pattern, "C:\foo\bar\baz")
matched
应该为true
的地方。
答案 3 :(得分:0)
试试这个代码。这将检查其中一个是否是另一个的子目录。尝试更改 base 和 path 的值,结果应该是有效的。
package main
import (
"fmt"
"path/filepath"
"strings"
)
func main() {
base := "/b/c/"
path := "/a/b/c/d"
if len(base) > len(path) {
base, path = path, base
}
rel, err := filepath.Rel(base, path)
fmt.Printf("Base %q: Path %q: Rel %q Err %v\n", base, path, rel, err)
if err != nil {
fmt.Println("PROCEED")
return
}
if strings.Contains(rel, "..") {
fmt.Println("PROCEED")
return
}
fmt.Println("DENY")
}