path/filepath is path applied to real files: it uses the operating system's separator, understands Windows volumes, and can read the disk to resolve symlinks.
Examples
They share most of their names. The difference is the separator: path always uses a forward slash, filepath uses whatever the OS uses.
// Same result on Unix, different on Windows.
fmt.Println(path.Join("a", "b")) // a/b everywhere
fmt.Println(filepath.Join("a", "b")) // a\b on Windows
// Rule of thumb: URLs and import paths use path,
// anything touching disk uses filepath.Output
a/b
a/bAbs resolves against the working directory. Rel goes the other way, computing the route from one path to another.
abs, err := filepath.Abs("main.go")
if err != nil {
log.Fatal(err)
}
fmt.Println(filepath.Base(abs))
rel, _ := filepath.Rel("/usr/local", "/usr/local/bin/go")
fmt.Println(rel)Output
main.go
bin/goWalkDir visits every file below a root. It is cheaper than the older Walk because fs.DirEntry avoids a Stat call per entry.
err := filepath.WalkDir(".", func(p string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() && d.Name() == ".git" {
return filepath.SkipDir // do not descend
}
if filepath.Ext(p) == ".go" {
fmt.Println(p)
}
return nil
})Output
main.go
cmd/tool/main.go
internal/db/db.goToSlash and FromSlash convert between OS paths and slash paths, which is what you want when a path goes into a URL, a zip file, or a config read on another machine.
p := filepath.Join("static", "css", "site.css")
// Safe to put in a URL or an archive entry.
fmt.Println(filepath.ToSlash(p))
// PATH-style lists split on the OS list separator.
fmt.Println(filepath.SplitList("/a:/b"))Output
static/css/site.css
[/a /b]| Function | Description |
|---|---|
Join(elem ...string) string filepath.Join("a", "b", "..", "c") // "a/c" | Joins with the OS separator and cleans the result. |
Split(p string) (dir, file string) | Splits after the final separator. dir keeps its trailing separator. |
Base(p string) string | The last element of the path. |
Dir(p string) string | Everything but the last element, cleaned. |
Ext(p string) string filepath.Ext("archive.tar.gz") // ".gz" | The extension including the dot. |
Clean(p string) string | Lexical cleanup only. It never reads the filesystem, so it can resolve .. through a symlink incorrectly. |
Abs(p string) (string, error) | Turns a relative path into an absolute one against the current working directory. |
Rel(basepath, targpath string) (string, error) filepath.Rel("/usr/local", "/usr/local/bin/go") // "bin/go" | The relative path from base to target. |
IsAbs(p string) bool | Reports whether the path is absolute for this OS. |
EvalSymlinks(p string) (string, error) | Resolves every symlink in the path, reading the filesystem to do it. |
Walk(root string, fn WalkFunc) error | Walks the tree rooted at root. Superseded by WalkDir, which avoids a Stat per entry. |
WalkDir(root string, fn fs.WalkDirFunc) error | Walks the tree using fs.DirEntry, which is cheaper than Walk. Prefer this. |
Glob(pattern string) ([]string, error) filepath.Glob("*.go") | Every filename matching the pattern, sorted. Returns nil with no error when nothing matches. |
Match(pattern, name string) (bool, error) | Reports whether name matches the pattern. Separator-aware. |
ToSlash(p string) string | Replaces OS separators with forward slashes, for writing a path into a URL or an archive. |
FromSlash(p string) string | The reverse: forward slashes become OS separators. |
SplitList(p string) []string filepath.SplitList("/a:/b") // ["/a" "/b"] | Splits a PATH-style list on the OS list separator. |
VolumeName(p string) string | The leading volume, like "C:" on Windows. Empty on Unix. |
Separator | The OS path separator: '/' on Unix, '\\' on Windows. |
ListSeparator | The OS list separator: ':' on Unix, ';' on Windows. |
Related: path os io/fs