check if given path is a subdirectory of another in golang

You could try and use path.filepath.Rel():

func Rel(basepath, targpath string) (string, error)

Rel returns a relative path that is lexically equivalent to targpath when joined to basepath with an intervening separator.
That is, Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself

That means Rel("c:\foo\bar", "c:\foo\bar\baz") should be baz, meaning a subpath completely included in c:\foo\bar\baz, and without any '../'.
The same would apply for unix paths.

That would make c:\foo\bar\baz a subdirectory of c:\foo\bar.


I haven't found a reliable solution for all types of paths, but the best you can get is by using filepath.Rel as VonC suggested.

It works if both filepaths are either absolute or relative (mixing is not allowed) and works on both Windows and 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
}

Absolute windows paths that start with a drive letter will require an additional check though.


You can use the function path.filepath.Match()

Match reports whether name matches the shell file name pattern.

For example:

pattern := "C:\foo\bar" + string(filepath.Separator) + "*"
matched, err := filepath.Match(pattern, "C:\foo\bar\baz")

Where matched should be true.

Tags:

Go