{"id":13412782,"url":"https://github.com/spf13/afero","last_synced_at":"2025-09-09T20:46:06.200Z","repository":{"id":22532194,"uuid":"25872841","full_name":"spf13/afero","owner":"spf13","description":"The Universal Filesystem Abstraction for Go","archived":false,"fork":false,"pushed_at":"2025-08-19T08:08:19.000Z","size":526,"stargazers_count":6308,"open_issues_count":159,"forks_count":539,"subscribers_count":91,"default_branch":"master","last_synced_at":"2025-08-21T13:38:52.007Z","etag":null,"topics":["compression","filesystem","fs","go","golang","network-file-system","network-file-transfer","vfs","virtual"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spf13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-10-28T14:19:05.000Z","updated_at":"2025-08-21T11:53:53.000Z","dependencies_parsed_at":"2023-02-16T20:32:01.871Z","dependency_job_id":"cfa15e29-11cd-4f36-9a62-0f2c6d9143f1","html_url":"https://github.com/spf13/afero","commit_stats":{"total_commits":286,"total_committers":81,"mean_commits":"3.5308641975308643","dds":0.8251748251748252,"last_synced_commit":"5c4385aa20510dba5ca4db12c02b0c9211d82892"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/spf13/afero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spf13%2Fafero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spf13%2Fafero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spf13%2Fafero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spf13%2Fafero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spf13","download_url":"https://codeload.github.com/spf13/afero/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spf13%2Fafero/sbom","scorecard":{"id":841245,"data":{"date":"2025-08-22T00:46:22Z","repo":{"name":"github.com/spf13/afero","commit":"2fb20ad3b2f7a6be83bd142888ea702c3388d3cc"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":5.6,"checks":[{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yaml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Code-Review","score":3,"reason":"Found 2/6 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Maintained","score":7,"reason":"9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:   9 out of   9 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/analysis-scorecard.yaml:19","Info: jobLevel 'contents' permission set to 'read': .github/workflows/analysis-scorecard.yaml:20","Info: topLevel 'contents' permission set to 'read': .github/workflows/analysis-scorecard.yaml:11","Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"CI-Tests","score":10,"reason":"14 out of 14 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}},{"name":"Contributors","score":10,"reason":"project has 45 contributing companies or organizations","details":["Info: found contributions from: IBM, NixOS, Thirdship, ToucanProtocol, bank-vaults, banzaicloud, cisco-open, code-423n4, coderwall-beaver, coderwall-charity, coderwall-forked, coderwall-forked100, coderwall-forked20, coderwall-forked50, coderwall-lemmings100, coderwall-lemmings1000, coderwall-mongoose, coderwall-nephilaKomaci, coderwall-polygamous, coderwall-python, dexidp, dottyland, emperror, fsnotify, go-viper, gofrs, gohugoio, guzzle, ibm, junohq, kube-logging, logur, mellanox-senior-design, nautilus, php-fig, php-http, portward, remerge, stlink-org, syncthing, teledyne adimec, thephpleague, twirphp, twosigma, zalando"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}}]},"last_synced_at":"2025-08-23T20:32:03.711Z","repository_id":22532194,"created_at":"2025-08-23T20:32:03.711Z","updated_at":"2025-08-23T20:32:03.711Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274359027,"owners_count":25270683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compression","filesystem","fs","go","golang","network-file-system","network-file-transfer","vfs","virtual"],"created_at":"2024-07-30T20:01:29.130Z","updated_at":"2025-09-09T20:46:06.184Z","avatar_url":"https://github.com/spf13.png","language":"Go","readme":"\u003cimg src=\"https://cloud.githubusercontent.com/assets/173412/11490338/d50e16dc-97a5-11e5-8b12-019a300d0fcb.png\" alt=\"afero logo-sm\"/\u003e\n\n\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/afero/ci.yaml?branch=master\u0026amp;style=flat-square)](https://github.com/spf13/afero/actions?query=workflow%3ACI)\n[![GoDoc](https://pkg.go.dev/badge/mod/github.com/spf13/afero)](https://pkg.go.dev/mod/github.com/spf13/afero)\n[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/afero)](https://goreportcard.com/report/github.com/spf13/afero)\n![Go Version](https://img.shields.io/badge/go%20version-%3E=1.23-61CFDD.svg?style=flat-square\")\n\n\n# Afero: The Universal Filesystem Abstraction for Go\n\nAfero is a powerful and extensible filesystem abstraction system for Go. It provides a single, unified API for interacting with diverse filesystems—including the local disk, memory, archives, and network storage.\n\nAfero acts as a drop-in replacement for the standard `os` package, enabling you to write modular code that is agnostic to the underlying storage, dramatically simplifies testing, and allows for sophisticated architectural patterns through filesystem composition.\n\n## Why Afero?\n\nAfero elevates filesystem interaction beyond simple file reading and writing, offering solutions for testability, flexibility, and advanced architecture.\n\n🔑 **Key Features:**\n\n*   **Universal API:** Write your code once. Run it against the local OS, in-memory storage, ZIP/TAR archives, or remote systems (SFTP, GCS).\n*   **Ultimate Testability:** Utilize `MemMapFs`, a fully concurrent-safe, read/write in-memory filesystem. Write fast, isolated, and reliable unit tests without touching the physical disk or worrying about cleanup.\n*   **Powerful Composition:** Afero's hidden superpower. Layer filesystems on top of each other to create sophisticated behaviors:\n    *   **Sandboxing:** Use `CopyOnWriteFs` to create temporary scratch spaces that isolate changes from the base filesystem.\n    *   **Caching:** Use `CacheOnReadFs` to automatically layer a fast cache (like memory) over a slow backend (like a network drive).\n    *   **Security Jails:** Use `BasePathFs` to restrict application access to a specific subdirectory (chroot).\n*   **`os` Package Compatibility:** Afero mirrors the functions in the standard `os` package, making adoption and refactoring seamless.\n*   **`io/fs` Compatibility:** Fully compatible with the Go standard library's `io/fs` interfaces.\n\n## Installation\n\n```bash\ngo get github.com/spf13/afero\n```\n\n```go\nimport \"github.com/spf13/afero\"\n```\n\n## Quick Start: The Power of Abstraction\n\nThe core of Afero is the `afero.Fs` interface. By designing your functions to accept this interface rather than calling `os.*` functions directly, your code instantly becomes more flexible and testable.\n\n### 1. Refactor Your Code\n\nChange functions that rely on the `os` package to accept `afero.Fs`.\n\n```go\n// Before: Coupled to the OS and difficult to test\n// func ProcessConfiguration(path string) error {\n//     data, err := os.ReadFile(path)\n//     ...\n// }\n\nimport \"github.com/spf13/afero\"\n\n// After: Decoupled, flexible, and testable\nfunc ProcessConfiguration(fs afero.Fs, path string) error {\n    // Use Afero utility functions which mirror os/ioutil\n    data, err := afero.ReadFile(fs, path)\n    // ... process the data\n    return err\n}\n```\n\n### 2. Usage in Production\n\nIn your production environment, inject the `OsFs` backend, which wraps the standard operating system calls.\n\n```go\nfunc main() {\n    // Use the real OS filesystem\n    AppFs := afero.NewOsFs()\n    ProcessConfiguration(AppFs, \"/etc/myapp.conf\")\n}\n```\n\n### 3. Usage in Testing\n\nIn your tests, inject `MemMapFs`. This provides a blazing-fast, isolated, in-memory filesystem that requires no disk I/O and no cleanup.\n\n```go\nfunc TestProcessConfiguration(t *testing.T) {\n    // Use the in-memory filesystem\n    AppFs := afero.NewMemMapFs()\n    \n    // Pre-populate the memory filesystem for the test\n    configPath := \"/test/config.json\"\n    afero.WriteFile(AppFs, configPath, []byte(`{\"feature\": true}`), 0644)\n\n    // Run the test entirely in memory\n    err := ProcessConfiguration(AppFs, configPath)\n    if err != nil {\n        t.Fatal(err)\n    }\n}\n```\n\n## Afero's Superpower: Composition\n\nAfero's most unique feature is its ability to combine filesystems. This allows you to build complex behaviors out of simple components, keeping your application logic clean.\n\n### Example 1: Sandboxing with Copy-on-Write\n\nCreate a temporary environment where an application can \"modify\" system files without affecting the actual disk.\n\n```go\n// 1. The base layer is the real OS, made read-only for safety.\nbaseFs := afero.NewReadOnlyFs(afero.NewOsFs())\n\n// 2. The overlay layer is a temporary in-memory filesystem for changes.\noverlayFs := afero.NewMemMapFs()\n\n// 3. Combine them. Reads fall through to the base; writes only hit the overlay.\nsandboxFs := afero.NewCopyOnWriteFs(baseFs, overlayFs)\n\n// The application can now \"modify\" /etc/hosts, but the changes are isolated in memory.\nafero.WriteFile(sandboxFs, \"/etc/hosts\", []byte(\"127.0.0.1 sandboxed-app\"), 0644)\n\n// The real /etc/hosts on disk is untouched.\n```\n\n### Example 2: Caching a Slow Filesystem\n\nImprove performance by layering a fast cache (like memory) over a slow backend (like a network drive or cloud storage).\n\n```go\nimport \"time\"\n\n// Assume 'remoteFs' is a slow backend (e.g., SFTP or GCS)\nvar remoteFs afero.Fs \n\n// 'cacheFs' is a fast in-memory backend\ncacheFs := afero.NewMemMapFs()\n\n// Create the caching layer. Cache items for 5 minutes upon first read.\ncachedFs := afero.NewCacheOnReadFs(remoteFs, cacheFs, 5*time.Minute)\n\n// The first read is slow (fetches from remote, then caches)\ndata1, _ := afero.ReadFile(cachedFs, \"data.json\")\n\n// The second read is instant (serves from memory cache)\ndata2, _ := afero.ReadFile(cachedFs, \"data.json\")\n```\n\n### Example 3: Security Jails (chroot)\n\nRestrict an application component's access to a specific subdirectory.\n\n```go\nosFs := afero.NewOsFs()\n\n// Create a filesystem rooted at /home/user/public\n// The application cannot access anything above this directory.\njailedFs := afero.NewBasePathFs(osFs, \"/home/user/public\")\n\n// To the application, this is reading \"/\"\n// In reality, it's reading \"/home/user/public/\"\ndirInfo, err := afero.ReadDir(jailedFs, \"/\")\n\n// Attempts to access parent directories fail\n_, err = jailedFs.Open(\"../secrets.txt\") // Returns an error\n```\n\n## Real-World Use Cases\n\n### Build Cloud-Agnostic Applications\n\nWrite applications that seamlessly work with different storage backends:\n\n```go\ntype DocumentProcessor struct {\n    fs afero.Fs\n}\n\nfunc NewDocumentProcessor(fs afero.Fs) *DocumentProcessor {\n    return \u0026DocumentProcessor{fs: fs}\n}\n\nfunc (p *DocumentProcessor) Process(inputPath, outputPath string) error {\n    // This code works whether fs is local disk, cloud storage, or memory\n    content, err := afero.ReadFile(p.fs, inputPath)\n    if err != nil {\n        return err\n    }\n    \n    processed := processContent(content)\n    return afero.WriteFile(p.fs, outputPath, processed, 0644)\n}\n\n// Use with local filesystem\nprocessor := NewDocumentProcessor(afero.NewOsFs())\n\n// Use with Google Cloud Storage\nprocessor := NewDocumentProcessor(gcsFS)\n\n// Use with in-memory filesystem for testing\nprocessor := NewDocumentProcessor(afero.NewMemMapFs())\n```\n\n### Treating Archives as Filesystems\n\nRead files directly from `.zip` or `.tar` archives without unpacking them to disk first.\n\n```go\nimport (\n    \"archive/zip\"\n    \"github.com/spf13/afero/zipfs\"\n)\n\n// Assume 'zipReader' is a *zip.Reader initialized from a file or memory\nvar zipReader *zip.Reader \n\n// Create a read-only ZipFs\narchiveFS := zipfs.New(zipReader)\n\n// Read a file from within the archive using the standard Afero API\ncontent, err := afero.ReadFile(archiveFS, \"/docs/readme.md\")\n```\n\n### Serving Any Filesystem over HTTP\n\nUse `HttpFs` to expose any Afero filesystem—even one created dynamically in memory—through a standard Go web server.\n\n```go\nimport (\n    \"net/http\"\n    \"github.com/spf13/afero\"\n)\n\nfunc main() {\n    memFS := afero.NewMemMapFs()\n    afero.WriteFile(memFS, \"index.html\", []byte(\"\u003ch1\u003eHello from Memory!\u003c/h1\u003e\"), 0644)\n\n    // Wrap the memory filesystem to make it compatible with http.FileServer.\n    httpFS := afero.NewHttpFs(memFS)\n\n    http.Handle(\"/\", http.FileServer(httpFS.Dir(\"/\")))\n    http.ListenAndServe(\":8080\", nil)\n}\n```\n\n### Testing Made Simple\n\nOne of Afero's greatest strengths is making filesystem-dependent code easily testable:\n\n```go\nfunc SaveUserData(fs afero.Fs, userID string, data []byte) error {\n    filename := fmt.Sprintf(\"users/%s.json\", userID)\n    return afero.WriteFile(fs, filename, data, 0644)\n}\n\nfunc TestSaveUserData(t *testing.T) {\n    // Create a clean, fast, in-memory filesystem for testing\n    testFS := afero.NewMemMapFs()\n    \n    userData := []byte(`{\"name\": \"John\", \"email\": \"john@example.com\"}`)\n    err := SaveUserData(testFS, \"123\", userData)\n    \n    if err != nil {\n        t.Fatalf(\"SaveUserData failed: %v\", err)\n    }\n    \n    // Verify the file was saved correctly\n    saved, err := afero.ReadFile(testFS, \"users/123.json\")\n    if err != nil {\n        t.Fatalf(\"Failed to read saved file: %v\", err)\n    }\n    \n    if string(saved) != string(userData) {\n        t.Errorf(\"Data mismatch: got %s, want %s\", saved, userData)\n    }\n}\n```\n\n**Benefits of testing with Afero:**\n- ⚡ **Fast** - No disk I/O, tests run in memory\n- 🔄 **Reliable** - Each test starts with a clean slate\n- 🧹 **No cleanup** - Memory is automatically freed\n- 🔒 **Safe** - Can't accidentally modify real files\n- 🏃 **Parallel** - Tests can run concurrently without conflicts\n\n## Backend Reference\n\n| Type | Backend | Constructor | Description | Status |\n| :--- | :--- | :--- | :--- | :--- |\n| **Core** | **OsFs** | `afero.NewOsFs()` | Interacts with the real operating system filesystem. Use in production. | ✅ Official |\n| | **MemMapFs** | `afero.NewMemMapFs()` | A fast, atomic, concurrent-safe, in-memory filesystem. Ideal for testing. | ✅ Official |\n| **Composition** | **CopyOnWriteFs**| `afero.NewCopyOnWriteFs(base, overlay)` | A read-only base with a writable overlay. Ideal for sandboxing. | ✅ Official |\n| | **CacheOnReadFs**| `afero.NewCacheOnReadFs(base, cache, ttl)` | Lazily caches files from a slow base into a fast layer on first read. | ✅ Official |\n| | **BasePathFs** | `afero.NewBasePathFs(source, path)` | Restricts operations to a subdirectory (chroot/jail). | ✅ Official |\n| | **ReadOnlyFs** | `afero.NewReadOnlyFs(source)` | Provides a read-only view, preventing any modifications. | ✅ Official |\n| | **RegexpFs** | `afero.NewRegexpFs(source, regexp)` | Filters a filesystem, only showing files that match a regex. | ✅ Official |\n| **Utility** | **HttpFs** | `afero.NewHttpFs(source)` | Wraps any Afero filesystem to be served via `http.FileServer`. | ✅ Official |\n| **Archives** | **ZipFs** | `zipfs.New(zipReader)` | Read-only access to files within a ZIP archive. | ✅ Official |\n| | **TarFs** | `tarfs.New(tarReader)` | Read-only access to files within a TAR archive. | ✅ Official |\n| **Network** | **GcsFs** | `gcsfs.NewGcsFs(...)` | Google Cloud Storage backend. | ⚡ Experimental |\n| | **SftpFs** | `sftpfs.New(...)` | SFTP backend. | ⚡ Experimental |\n| **3rd Party Cloud** | **S3Fs** | [`fclairamb/afero-s3`](https://github.com/fclairamb/afero-s3) | Production-ready S3 backend built on official AWS SDK. | 🔹 3rd Party |\n| | **MinioFs** | [`cpyun/afero-minio`](https://github.com/cpyun/afero-minio) | MinIO object storage backend with S3 compatibility. | 🔹 3rd Party |\n| | **DriveFs** | [`fclairamb/afero-gdrive`](https://github.com/fclairamb/afero-gdrive) | Google Drive backend with streaming support. | 🔹 3rd Party |\n| | **DropboxFs** | [`fclairamb/afero-dropbox`](https://github.com/fclairamb/afero-dropbox) | Dropbox backend with streaming support. | 🔹 3rd Party |\n| **3rd Party Specialized** | **GitFs** | [`tobiash/go-gitfs`](https://github.com/tobiash/go-gitfs) | Git repository filesystem (read-only, Afero compatible). | 🔹 3rd Party |\n| | **DockerFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | Docker container filesystem access. | 🔹 3rd Party |\n| | **GitHubFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | GitHub repository and releases filesystem. | 🔹 3rd Party |\n| | **FilterFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | Filesystem filtering with predicates. | 🔹 3rd Party |\n| | **IgnoreFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | .gitignore-aware filtering filesystem. | 🔹 3rd Party |\n| | **FUSEFs** | [`JakWai01/sile-fystem`](https://github.com/JakWai01/sile-fystem) | Generic FUSE implementation using any Afero backend. | 🔹 3rd Party |\n\n## Afero vs. `io/fs` (Go 1.16+)\n\nGo 1.16 introduced the `io/fs` package, which provides a standard abstraction for **read-only** filesystems.\n\nAfero complements `io/fs` by focusing on different needs:\n\n*   **Use `io/fs` when:** You only need to read files and want to conform strictly to the standard library interfaces.\n*   **Use Afero when:**\n    *   Your application needs to **create, write, modify, or delete** files.\n    *   You need to test complex read/write interactions (e.g., renaming, concurrent writes).\n    *   You need advanced compositional features (Copy-on-Write, Caching, etc.).\n\nAfero is fully compatible with `io/fs`. You can wrap any Afero filesystem to satisfy the `fs.FS` interface using `afero.NewIOFS`:\n\n```go\nimport \"io/fs\"\n\n// Create an Afero filesystem (writable)\nvar myAferoFs afero.Fs = afero.NewMemMapFs()\n\n// Convert it to a standard library fs.FS (read-only view)\nvar myIoFs fs.FS = afero.NewIOFS(myAferoFs)\n```\n\n## Third-Party Backends \u0026 Ecosystem\n\nThe Afero community has developed numerous backends and tools that extend the library's capabilities. Below are curated, well-maintained options organized by maturity and reliability.\n\n### Featured Community Backends\n\nThese are mature, reliable backends that we can confidently recommend for production use:\n\n#### **Amazon S3** - [`fclairamb/afero-s3`](https://github.com/fclairamb/afero-s3)\nProduction-ready S3 backend built on the official AWS SDK for Go.\n\n```go\nimport \"github.com/fclairamb/afero-s3\"\n\ns3fs := s3.NewFs(bucket, session)\n```\n\n#### **MinIO** - [`cpyun/afero-minio`](https://github.com/cpyun/afero-minio)\nMinIO object storage backend providing S3-compatible object storage with deduplication and optimization features.\n\n```go\nimport \"github.com/cpyun/afero-minio\"\n\nminioFs := miniofs.NewMinioFs(ctx, \"minio://endpoint/bucket\")\n```\n\n### Community \u0026 Specialized Backends\n\n#### Cloud Storage\n\n- **Google Drive** - [`fclairamb/afero-gdrive`](https://github.com/fclairamb/afero-gdrive)  \n  Streaming support; no write-seeking or POSIX permissions; no files listing cache\n\n- **Dropbox** - [`fclairamb/afero-dropbox`](https://github.com/fclairamb/afero-dropbox)  \n  Streaming support; no write-seeking or POSIX permissions\n\n#### Version Control Systems\n\n- **Git Repositories** - [`tobiash/go-gitfs`](https://github.com/tobiash/go-gitfs)  \n  Read-only filesystem abstraction for Git repositories. Works with bare repositories and provides filesystem view of any git reference. Uses go-git for repository access.\n\n#### Container and Remote Systems\n\n- **Docker Containers** - [`unmango/aferox`](https://github.com/unmango/aferox)  \n  Access Docker container filesystems as if they were local filesystems\n\n- **GitHub API** - [`unmango/aferox`](https://github.com/unmango/aferox)  \n  Turn GitHub repositories, releases, and assets into browsable filesystems\n\n#### FUSE Integration\n\n- **Generic FUSE** - [`JakWai01/sile-fystem`](https://github.com/JakWai01/sile-fystem)  \n  Mount any Afero filesystem as a FUSE filesystem, allowing any Afero backend to be used as a real mounted filesystem\n\n#### Specialized Filesystems\n\n- **FAT32 Support** - [`aligator/GoFAT`](https://github.com/aligator/GoFAT)  \n  Pure Go FAT filesystem implementation (currently read-only)\n\n### Interface Adapters \u0026 Utilities\n\n**Cross-Interface Compatibility:**\n- [`jfontan/go-billy-desfacer`](https://github.com/jfontan/go-billy-desfacer) - Adapter between Afero and go-billy interfaces (for go-git compatibility)\n- [`Maldris/go-billy-afero`](https://github.com/Maldris/go-billy-afero) - Alternative wrapper for using Afero with go-billy\n- [`c4milo/afero2billy`](https://github.com/c4milo/afero2billy) - Another Afero to billy filesystem adapter\n\n**Working Directory Management:**\n- [`carolynvs/aferox`](https://github.com/carolynvs/aferox) - Working directory-aware filesystem wrapper\n\n**Advanced Filtering:**\n- [`unmango/aferox`](https://github.com/unmango/aferox) includes multiple specialized filesystems:\n  - **FilterFs** - Predicate-based file filtering\n  - **IgnoreFs** - .gitignore-aware filtering\n  - **WriterFs** - Dump writes to io.Writer for debugging\n\n#### Developer Tools \u0026 Utilities\n\n**nhatthm Utility Suite** - Essential tools for Afero development:\n- [`nhatthm/aferocopy`](https://github.com/nhatthm/aferocopy) - Copy files between any Afero filesystems\n- [`nhatthm/aferomock`](https://github.com/nhatthm/aferomock) - Mocking toolkit for testing\n- [`nhatthm/aferoassert`](https://github.com/nhatthm/aferoassert) - Assertion helpers for filesystem testing\n\n### Ecosystem Showcase\n\n**Windows Virtual Drives** - [`balazsgrill/potatodrive`](https://github.com/balazsgrill/potatodrive)  \nMount any Afero filesystem as a Windows drive letter. Brilliant demonstration of Afero's power!\n\n### Modern Asset Embedding (Go 1.16+)\n\nInstead of third-party tools, use Go's native `//go:embed` with Afero:\n\n```go\nimport (\n    \"embed\"\n    \"github.com/spf13/afero\"\n)\n\n//go:embed assets/*\nvar assetsFS embed.FS\n\nfunc main() {\n    // Convert embedded files to Afero filesystem\n    fs := afero.FromIOFS(assetsFS)\n    \n    // Use like any other Afero filesystem\n    content, _ := afero.ReadFile(fs, \"assets/config.json\")\n}\n```\n\n## Contributing\n\nWe welcome contributions! The project is mature, but we are actively looking for contributors to help implement and stabilize network/cloud backends.\n\n* 🔥 **Microsoft Azure Blob Storage**  \n* 🔒 **Modern Encryption Backend** - Built on secure, contemporary crypto (not legacy EncFS)  \n* 🐙 **Canonical go-git Adapter** - Unified solution for Git integration  \n* 📡 **SSH/SCP Backend** - Secure remote file operations  \n*  Stabilization of existing experimental backends (GCS, SFTP)\n\nTo contribute:\n1. Fork the repository\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## 📄 License\n\nAfero is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt) for details.\n\n## 🔗 Additional Resources\n\n- [📖 Full API Documentation](https://pkg.go.dev/github.com/spf13/afero)\n- [🎯 Examples Repository](https://github.com/spf13/afero/tree/master/examples)\n- [📋 Release Notes](https://github.com/spf13/afero/releases)\n- [❓ GitHub Discussions](https://github.com/spf13/afero/discussions)\n\n---\n\n*Afero comes from the Latin roots Ad-Facere, meaning \"to make\" or \"to do\" - fitting for a library that empowers you to make and do amazing things with filesystems.*\n","funding_links":[],"categories":["HarmonyOS","Files","Go","开源类库","File System","Misc","Programming","Open source library","File Handling","Miscellaneous","project","文件","文件处理","文件处理`处理文件和文件系统操作的库`","\u003cspan id=\"文件-files\"\u003e文件 Files\u003c/span\u003e","Relational Databases"],"sub_categories":["Windows Manager","Advanced Console UIs","文件/存储","Golang","Files/Storage","Search and Analytic Databases","SQL 查询语句构建库","检索及分析资料库","高级控制台界面","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","高級控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspf13%2Fafero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspf13%2Fafero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspf13%2Fafero/lists"}