I think a nice platform-independent solution is to use the golang path/filepath Split function. Does not make assumptions about what path separators look like, handles volumes, etc...
import (
"path/filepath"
)
func subpath(homeDir, prevDir string) string {
subFiles := ""
for {
dir, file := filepath.Split(prevDir)
if len(subFiles) > 0 {
subFiles = file + string(filepath.Separator) + subFiles
} else {
subFiles = file
}
if file == homeDir {
break
}
if len(dir) == 0 || dir == prevDir {
break
}
prevDir = dir[:len(dir) - 1]
}
return subFiles
}
Call with
subpath("home", "allusers/user/home/path/to/file")
To handle cases where "home" may appear more than once and you wish to match the first:
func subpath(homeDir, prevDir string) (subFiles string, found bool) {
for {
dir, file := filepath.Split(prevDir)
if len(subFiles) > 0 {
subFiles = file + string(filepath.Separator) + subFiles
} else {
subFiles = file
}
if len(dir) == 0 || dir == prevDir {
return
}
prevDir = dir[:len(dir) - 1]
if file == homeDir {
found = true
// look for it lower down
lower, foundAgain := subpath(homeDir, prevDir)
if foundAgain {
subFiles = lower + string(filepath.Separator) + subFiles
}
return
}
}
}
Call with
path, found = subpath("home", "allusers/user/home/path/home2/home/to/file")
if found {
fmt.Printf("%q
", path)
} else {
fmt.Printf("not found
")
}