absfs is a go package that defines an abstract filesystem interface.
The design goal of absfs is to support a system of composable filesystem implementations for various uses from testing to complex storage management.
Implementors can create stand alone filesystems that implement the absfs.Filer interface providing new components that can easily be added to existing compositions and data pipelines.
- 📦 Composable - Layer filesystems for complex behaviors
- 🧪 Testable - Mock filesystems for unit testing
- 🔧 Extensible - Easy to implement new filesystem types
- 🚀 Performant - Minimal overhead wrapper pattern
- 📚 Well-documented - Comprehensive docs and examples
- ✅ Well-tested - 89% code coverage
- 🌍 Cross-platform - Unix-style paths work on Windows, macOS, and Linux
$ go get github.com/absfs/absfsabsfs defines 4 interfaces.
Filer- The minimum set of methods that an implementation must define.FileSystem- The complete set of Abstract FileSystem methods, including convenience functions.SymLinker- Methods for implementing symbolic links.SymlinkFileSystem- A FileSystem that supports symbolic links.
The minimum set of methods that an implementation must define.
type Filer interface {
Mkdir(name string, perm os.FileMode) error
OpenFile(name string, flag int, perm os.FileMode) (File, error)
Remove(name string) error
Rename(oldname, newname string) error
Stat(name string) (os.FileInfo, error)
Chmod(name string, mode os.FileMode) error
Chtimes(name string, atime time.Time, mtime time.Time) error
Chown(name string, uid, gid int) error
// io/fs compatibility methods
ReadDir(name string) ([]fs.DirEntry, error)
ReadFile(name string) ([]byte, error)
Sub(dir string) (fs.FS, error)
}The complete set of Abstract FileSystem methods, including convenience functions.
type FileSystem interface {
// Filer interface
OpenFile(name string, flag int, perm os.FileMode) (File, error)
Mkdir(name string, perm os.FileMode) error
Remove(name string) error
Rename(oldpath, newpath string) error
Stat(name string) (os.FileInfo, error)
Chmod(name string, mode os.FileMode) error
Chtimes(name string, atime time.Time, mtime time.Time) error
Chown(name string, uid, gid int) error
Chdir(dir string) error
Getwd() (dir string, err error)
TempDir() string
Open(name string) (File, error)
Create(name string) (File, error)
MkdirAll(name string, perm os.FileMode) error
RemoveAll(path string) (err error)
Truncate(name string, size int64) error
}Additional methods for implementing symbolic links.
type SymLinker interface {
Lstat(name string) (os.FileInfo, error)
Lchown(name string, uid, gid int) error
Readlink(name string) (string, error)
Symlink(oldname, newname string) error
}Windows Note: When using
osfson Windows, symlinks require elevated privileges or Developer Mode. See the osfs SYMLINKS.md for configuration instructions. Virtual filesystems (memfs, boltfs, etc.) support symlinks on all platforms without special configuration.
A FileSystem that supports symbolic links.
type SymlinkFileSystem interface {
// Filer interface
OpenFile(name string, flag int, perm os.FileMode) (File, error)
Mkdir(name string, perm os.FileMode) error
Remove(name string) error
Stat(name string) (os.FileInfo, error)
Chmod(name string, mode os.FileMode) error
Chtimes(name string, atime time.Time, mtime time.Time) error
Chown(name string, uid, gid int) error
// FileSystem interface
Chdir(dir string) error
Getwd() (dir string, err error)
TempDir() string
Open(name string) (File, error)
Create(name string) (File, error)
MkdirAll(name string, perm os.FileMode) error
RemoveAll(path string) (err error)
Truncate(name string, size int64) error
// SymLinker interface
Lstat(name string) (os.FileInfo, error)
Lchown(name string, uid, gid int) error
Readlink(name string) (string, error)
Symlink(oldname, newname string) error
}An absfs.FileSystem implementation that wraps the equivalent os standard library filesystem functions. Using osfs is essentially identical to using the os package except that it implements a per object current working directory.
The memfs filesystem implements a memory only filesystem.
The Nil FileSystem is a no-op implementation. Methods have no effect and most return no errors. The Read and ReadAt methods always return io.EOF to avoid infinite loops.
The Pass Through FileSystem (ptfs) takes any object that implements absfs.FileSystem and passes all methods through unaltered to that object.
The rofs is a read-only filesystem that can wrap any other filesystem implementation and make it read only.
The basefs filesystem takes a absfs.FileSystem and an absolute path within that filesystem, and provides a absfs.FileSystem interface that is rooted at that path. Relative paths are handled correctly such that it is not possible to 'escape' the base path constraint (for example by using a path like "/.."). In addition errors are rewritten to accurately obscure the base path.
A filesystem that can convert a absfs.FileSystem to a http.FileSystem interface for use with http.FileServer.
CorFS (cache on read fs)
An absfs.Filer that wraps two absfs.Filers when data is read if it doesn't exist in the second tier filesytem the filer copies data from the underlying file systems into the second tier filesystem causing it to function like a cache.
CowFS (copy on write fs)
An absfs.Filer that wraps two absfs.Filers the first of which may be a read only filesystem. Any attempt to modify or write data to a CowFS causes the Filer to write those changes to the secondary fs leaving the underlying filesystem unmodified.
An absfs.Filer that provides and absfs.Filer interface for the popular embeddable key/value store called bolt.
An absfs.Filer that provides and absfs. Filer interface to any S3 compatible object storage API.
A filesystem which reads and writes securely between computers across networks using the SFTP interface.
See the User Guide for comprehensive documentation on using absfs in your applications, including:
- Working with files and directories
- Path handling across platforms
- Thread safety patterns
- Composition and testing strategies
For applications using the OS filesystem across Windows, macOS, and Linux, use this simple pattern:
// filesystem_windows.go
//go:build windows
func NewFS(drive string) absfs.FileSystem {
if drive == "" { drive = "C:" }
return osfs.NewWindowsDriveMapper(osfs.NewFS(), drive)
}
// filesystem_unix.go
//go:build !windows
func NewFS(drive string) absfs.FileSystem {
return osfs.NewFS()
}Then use Unix-style paths everywhere:
fs := NewFS("")
fs.Create("/config/app.json") // Works on all platforms!See PATH_HANDLING.md and examples/cross-platform for details.
Want to create your own filesystem implementation? See the Implementer Guide for complete instructions on implementing the Filer interface, including:
- Method-by-method requirements
- Security best practices
- Testing strategies
- Performance considerations
Each FileSystem object created by ExtendFiler maintains its own current working directory (cwd) state, which can be modified by Chdir. Concurrent access from multiple goroutines can cause race conditions.
-
One FileSystem per goroutine (Recommended)
func worker(id int) { fs := absfs.ExtendFiler(filer) // Each goroutine gets its own instance fs.Chdir(fmt.Sprintf("/worker%d", id)) // ... do work ... }
-
Use absolute paths only
// Shared filesystem is safe if you only use absolute paths sharedFS := absfs.ExtendFiler(filer) // Safe: no dependency on cwd sharedFS.Open("/absolute/path/to/file.txt")
-
External synchronization
var mu sync.Mutex sharedFS := absfs.ExtendFiler(filer) mu.Lock() sharedFS.Chdir("/some/directory") file, _ := sharedFS.Open("relative/file.txt") mu.Unlock()
See SECURITY.md for more details.
The absfs package provides consistent path semantics across all platforms. Paths starting with / or \ are treated as virtual absolute paths, allowing Unix-style paths to work on Windows while maintaining support for OS-native paths.
// These work identically on Unix, macOS, AND Windows:
fs := absfs.ExtendFiler(virtualFS)
fs.Create("/config/app.json")
fs.MkdirAll("/var/log/app", 0755)Important for Windows users: Paths like /config/file.txt are treated as virtual-absolute for portability. For true OS operations on Windows, use drive letters (C:\path) or UNC paths (\\server\share).
See PATH_HANDLING.md for comprehensive cross-platform path behavior documentation.
- User Guide - Complete guide to using absfs in your applications
- Path Handling Guide - Cross-platform path semantics
- Security Policy - Security considerations and best practices
- Implementer Guide - How to create custom filesystem implementations
- Architecture Guide - Design decisions and internal architecture
We strongly encourage contributions, please fork and submit Pull Requests, and publish any FileSystems you implement.
New FileSystem types do not need to be added to this repo, but we'd be happy to link to yours so please open an issue or better yet add a Pull Request with the updated Readme.
This project is governed by the MIT License. See LICENSE