fsglob is a Go package for finding file paths that match glob patterns. It operates by walking a filesystem and is designed to be cross-platform and extensible.
- Standard Glob Patterns: Supports common glob syntax for flexible matching.
- Cross-Platform Path Handling: Automatically handles both Windows (
\) and Unix (/) path separators in patterns. - Extensible Filesystem: Can operate on any filesystem that implements the provided
filesystem.Filesysteminterface, making it suitable for testing with mocks or for use with virtual filesystems.
go get github.com/your-username/fsglobThe main function in this package is fsglob.GetFiles(). It takes a pattern and returns a slice of all matching file and directory paths.
package main import ( "fmt" "log" "github.com/your-username/fsglob" ) func main() { // Example 1: Find all Go files recursively from the current directory. goFiles, err := fsglob.GetFiles("**/*.go") if err != nil { log.Fatalf("Failed to find Go files: %v", err) } fmt.Println("Found Go files:") for _, file := range goFiles { fmt.Println(file) } // Example 2: Find all Markdown or text files in a 'docs' directory. docFiles, err := fsglob.GetFiles("docs/*.{md,txt}") if err != nil { log.Fatalf("Failed to find doc files: %v", err) } fmt.Println("\nFound documentation files:") for _, file := range docFiles { fmt.Println(file) } }fsglob supports the following pattern syntax:
| Pattern | Description | Example |
|---|---|---|
* | Matches any sequence of characters, except for path separators (/ or \). | *.log |
? | Matches any single character. | file?.txt |
** | Matches zero or more directories, files, and subdirectories recursively. | reports/**/*.xml |
[] | Matches any single character within the brackets. Can be a set or a range. | [abc].go, [0-9].txt |
{} | Matches any of the comma-separated patterns within the braces. | image.{jpg,png,gif} |
For testing or working with virtual filesystems (e.g., in-memory, TAR files), you can use fsglob.NewGlob() to create a globber instance that operates on a custom filesystem.
Your custom filesystem must implement the filesystem.Filesystem interface, which is exposed by github.com/your-username/fsglob/filesystem.
package main import ( "fmt" "log" "github.com/your-username/fsglob" "github.com/your-username/fsglob/filesystem" ) // InMemoryFS is a simple in-memory implementation of filesystem.Filesystem. // (This is a conceptual example; a full implementation is required). type InMemoryFS struct { // ... fields to store files and directories in memory } // Implement the methods of the filesystem.Filesystem interface for InMemoryFS... func (fs *InMemoryFS) Stat(name string) (fs.FileInfo, error) { /* ... */ } func (fs *InMemoryFS) ReadDir(name string) ([]fs.DirEntry, error) { /* ... */ } func (fs *InMemoryFS) Getwd() (string, error) { /* ... */ } func (fs *InMemoryFS) Abs(path string) (string, error) { /* ... */ } // ... other methods func main() { // 1. Create an instance of your custom filesystem. memFS := &InMemoryFS{} // ... code to populate memFS with files and directories ... // 2. Create a new Glob instance with the custom filesystem. g := fsglob.NewGlob("/**/*.log", memFS) // 3. Use the Expand() method to find matches. matches, err := g.Expand() if err != nil { log.Fatalf("Error during glob expansion: %v", err) } fmt.Println("Log files found in the in-memory filesystem:") for _, match := range matches { fmt.Println(match) } }This project is licensed under the MIT License. See the LICENSE file for details.