{"id":27201127,"url":"https://github.com/gregl83/paq","last_synced_at":"2025-12-30T03:32:22.703Z","repository":{"id":57652723,"uuid":"439475653","full_name":"gregl83/paq","owner":"gregl83","description":"🌪️#️⃣ Fast Hashing of File or Directory","archived":false,"fork":false,"pushed_at":"2025-09-23T04:47:39.000Z","size":1157,"stargazers_count":20,"open_issues_count":12,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-23T06:15:49.280Z","etag":null,"topics":["blake3","cryptographic","directory-hash","directory-traversal","file-hashing","hash","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gregl83.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-17T22:30:07.000Z","updated_at":"2025-09-23T04:47:38.000Z","dependencies_parsed_at":"2024-05-30T19:33:53.869Z","dependency_job_id":"ee6ee13f-ff1b-49e0-b077-ce36e4ddc7ea","html_url":"https://github.com/gregl83/paq","commit_stats":{"total_commits":42,"total_committers":1,"mean_commits":42.0,"dds":0.0,"last_synced_commit":"b00646fc6e86b882a6cbe3cbf9ccf76781b978d5"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/gregl83/paq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregl83%2Fpaq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregl83%2Fpaq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregl83%2Fpaq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregl83%2Fpaq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gregl83","download_url":"https://codeload.github.com/gregl83/paq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregl83%2Fpaq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279009405,"owners_count":26084580,"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-10-11T02:00:06.511Z","response_time":55,"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":["blake3","cryptographic","directory-hash","directory-traversal","file-hashing","hash","rust"],"created_at":"2025-04-09T21:55:13.498Z","updated_at":"2025-12-30T03:32:22.697Z","avatar_url":"https://github.com/gregl83.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build](https://github.com/gregl83/paq/actions/workflows/build.yml/badge.svg)](https://github.com/gregl83/paq/actions/workflows/build.yml)\n[![Coverage Status](https://codecov.io/gh/gregl83/paq/graph/badge.svg?token=CL93O7DW9C)](https://codecov.io/gh/gregl83/paq)\n[![Crates.io](https://img.shields.io/crates/v/paq.svg)](https://crates.io/crates/paq)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/gregl83/paq/blob/master/LICENSE)\n\n# paq\n\nHash file or directory recursively.\n\nPowered by `blake3` cryptographic hashing algorithm.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"paq.gif\" alt=\"paq hashing demo\" /\u003e\n\u003c/p\u003e\n\n## Performance\n\nThe [Go](https://github.com/golang/go/commit/6e676ab2b809d46623acb5988248d95d1eb7939c) programming language repository was used as a test data source (157 MB / 14,490 files).\n\n| Tool                       | Version | Command                   |     Mean [ms] | Min [ms] | Max [ms] |     Relative |\n| :------------------------- | :------ | :------------------------ | ------------: | -------: | -------: | -----------: |\n| [paq][paq]                 | latest  | `paq ./go`                |    77.7 ± 0.6 |     77.1 |     80.2 |         1.00 |\n| [b3sum][b3sum]             | 1.5.1   | `find ./go ... b3sum`     |   327.3 ± 3.6 |    320.2 |    332.3 |  4.21 ± 0.05 |\n| [dirhash][dirhash]         | 0.5.0   | `dirhash -a sha256 ./go`  |   576.1 ± 2.9 |    570.8 |    580.3 |  7.41 ± 0.06 |\n| [GNU sha2][gnusha]         | 9.7     | `find ./go ... sha256sum` |  725.2 ± 43.5 |    692.2 |    813.2 |  9.33 ± 0.56 |\n| [folder-hash][folder-hash] | 4.1.1   | `folder-hash ./go`        | 1906.0 ± 78.0 |   1810.0 |   2029.0 | 24.53 ± 1.02 |\n\n[paq]: https://github.com/gregl83/paq\n[b3sum]: https://github.com/BLAKE3-team/BLAKE3/tree/master/b3sum\n[gnusha]: https://manpages.debian.org/testing/coreutils/sha256sum.1.en.html\n[dirhash]: https://github.com/andhus/dirhash-python\n[folder-hash]: https://github.com/marc136/node-folder-hash\n\nSee [benchmarks](docs/benchmarks.md) documentation for more details.\n\n## Installation\n\n### Pre-Built Binary\n\nWindows, macOS, and Ubuntu are supported.\n\n1. **Download:** Go to the [Latest Release](https://github.com/gregl83/paq/releases) page and download the `.zip` archive matching your OS and Architecture.\n2. **Extract:** Unzip the `.zip` archive to retrieve the `paq` binary.\n3. **Install:** Make the `paq` binary executable (e.g., `chmod +x`) and move it to a directory in your system PATH.\n4. **Verify:** Confirm installation by running `paq --version` from the Command Line Interface.\n\n### Cargo Install\n\nRequires the [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) package manager.\n\n#### Install From Crates.io\n\n```bash\ncargo install paq\n```\n\n#### Install From Repository Clone (Unstable)\n\nNot recommended due to instability of `main` branch in-between tagged releases.\n\n1. Clone this repository.\n2. Run `cargo install --path .` from repository root.\n\n### Nix Flakes\n\nRequires [nix](https://nix.dev/) and the `nix-command` [experimental feature](https://nixos.wiki/wiki/Flakes#Enable_flakes_temporarily) to be enabled.\n\n```bash\nnix profile add github:gregl83/paq\n```\n\n### Python Package\n\nSupport for Python is available in the [paqpy](https://github.com/gregl83/paqpy) package.\n\n## Usage\n\nCommand Line Interface executable or Crate library.\n\nIncluded in this repository is an [example directory](./example) containing some sample files, a subdirectory and a symlink to test `paq` functionality.\n\n### Executable\n\nRun `paq [src]` to hash source file or directory.\n\nOutput hash to `.paq` file as valid JSON.\n\nFor help, run `paq --help`.\n\n#### Hash Example Directory\n\n```bash\npaq ./example\n```\n\nPath to example directory can be relative or absolute.\n\nExpect different results if `-i` or `--ignore-hidden` flag argument is used.\n\n### Crate Library\n\nAdd `paq` to project [dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio) in `Cargo.toml`.\n\n#### Use Library\n\n```rust\nuse paq;\n\nlet source = std::path::PathBuf::from(\"/path/to/source\");\nlet ignore_hidden = true; // .dir or .file\nlet source_hash: paq::ArrayString\u003c64\u003e = paq::hash_source(\u0026source, ignore_hidden);\n\nprintln!(\"{}\", source_hash);\n```\n\n#### Hash Example Directory\n\n```rust\nuse paq;\n\nlet source = std::path::PathBuf::from(\"example\");\nlet ignore_hidden = true;\nlet source_hash: paq::ArrayString\u003c64\u003e = paq::hash_source(\u0026source, ignore_hidden);\n\nassert_eq!(\u0026source_hash[..], \"d7d25c9b2fdb7391e650085a985ad0d892c7f0dd5edd32c7ccdb4b0d1c34c430\");\n```\n\nExpect different results if `ignore_hidden` is set to `false`.\n\n## Content Limitations\n\nHashes are generated using file system content as input data to the `blake3` hashing algorithm.\n\nBy design, `paq` does NOT include file system metadata in hash input such as:\n\n- File modes\n- File ownership\n- File modification and access times\n- File ACLs and extended attributes\n- Hard links\n- Symlink target contents (target path is hashed)\n\nAdditionally, files or directory contents starting with dot or full stop _can_ optionally be ignored.\n\n## How it Works\n\n1. **Stream \u0026 Hash:** Recursively discovers source system path(s) and hashes them in a parallel pipeline.\n2. **Sort:** Orders the hashes to ensure a deterministic output.\n3. **Finalize:** Computes the final hash by hashing the list of hashes.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregl83%2Fpaq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgregl83%2Fpaq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregl83%2Fpaq/lists"}