RosettaCodeData/Task/Find-common-directory-path/Go/find-common-directory-path.go

80 lines
1.9 KiB
Go
Raw Permalink Normal View History

2013-04-10 21:29:02 -07:00
package main
2015-02-20 00:35:01 -05:00
import (
2013-04-10 21:29:02 -07:00
"fmt"
2015-02-20 00:35:01 -05:00
"os"
2013-04-10 21:29:02 -07:00
"path"
)
2015-02-20 00:35:01 -05:00
func CommonPrefix(sep byte, paths ...string) string {
2013-04-10 21:29:02 -07:00
// Handle special cases.
switch len(paths) {
2015-02-20 00:35:01 -05:00
case 0:
return ""
case 1:
return path.Clean(paths[0])
2013-04-10 21:29:02 -07:00
}
2015-02-20 00:35:01 -05:00
// Note, we treat string as []byte, not []rune as is often
// done in Go. (And sep as byte, not rune). This is because
// most/all supported OS' treat paths as string of non-zero
// bytes. A filename may be displayed as a sequence of Unicode
// runes (typically encoded as UTF-8) but paths are
// not required to be valid UTF-8 or in any normalized form
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
// file names.
2013-04-10 21:29:02 -07:00
c := []byte(path.Clean(paths[0]))
2015-02-20 00:35:01 -05:00
// We add a trailing sep to handle the case where the
// common prefix directory is included in the path list
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
// path.Clean will have cleaned off trailing / separators with
// the exception of the root directory, "/" (in which case we
// make it "//", but this will get fixed up to "/" bellow).
c = append(c, sep)
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
// Ignore the first path since it's already in c
for _, v := range paths[1:] {
// Clean up each path before testing it
v = path.Clean(v) + string(sep)
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
// Find the first non-common byte and truncate c
if len(v) < len(c) {
c = c[:len(v)]
}
for i := 0; i < len(c); i++ {
2013-04-10 21:29:02 -07:00
if v[i] != c[i] {
2015-02-20 00:35:01 -05:00
c = c[:i]
2013-04-10 21:29:02 -07:00
break
}
}
}
2015-02-20 00:35:01 -05:00
// Remove trailing non-separator characters and the final separator
for i := len(c) - 1; i >= 0; i-- {
if c[i] == sep {
c = c[:i]
2013-04-10 21:29:02 -07:00
break
}
}
return string(c)
}
func main() {
2015-02-20 00:35:01 -05:00
c := CommonPrefix(os.PathSeparator,
//"/home/user1/tmp",
2013-04-10 21:29:02 -07:00
"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members",
2015-02-20 00:35:01 -05:00
"/home//user1/tmp/coventry",
"/home/user1/././tmp/covertly/foo",
"/home/bob/../user1/tmp/coved/bar",
2013-04-10 21:29:02 -07:00
)
2015-02-20 00:35:01 -05:00
if c == "" {
fmt.Println("No common path")
} else {
fmt.Println("Common path:", c)
}
2013-04-10 21:29:02 -07:00
}