Skip to content
gregl83Public

Repository files navigation

CI Coverage Status Crates.io MIT licensed

paq

Hash a directory or file with BLAKE3.

paq hashing demo

Performance

The Go programming language repository was used as a test data source (157 MB / 14,490 files).

Tool Version Command Mean [ms] Min [ms] Max [ms] Relative
paq 2.0.0 paq ./go 30.0 ± 0.3 29.3 30.6 1.00
GNU md5sum 9.11 fd ... ./go ... md5sum 90.6 ± 6.9 79.6 102.6 3.02 ± 0.23
merkle_hash 3.9.0 merkle-hash ./go 98.7 ± 27.4 36.1 138.6 3.29 ± 0.91
b3sum 1.5.1 fd ... ./go ... b3sum 114.1 ± 3.6 108.3 119.5 3.80 ± 0.13
GNU sha2 9.11 fd ... ./go ... sha256sum 155.3 ± 11.7 140.1 191.2 5.17 ± 0.40
directory-checksum 1.4.20 directory-checksum --max-depth=0 ./go 386.5 ± 2.0 382.8 389.1 12.87 ± 0.15
checksumdir 1.3.0 checksumdir -a sha256 ./go 453.9 ± 6.8 447.3 471.0 15.11 ± 0.28
dirhash 0.5.0 dirhash -a sha256 ./go 570.0 ± 3.3 565.2 575.8 18.98 ± 0.23
folder-hash 4.1.1 folder-hash ./go 1407.0 ± 49.0 1318.0 1497.0 46.86 ± 1.72
Hashrat 1.25 hashrat -sha256 -dir -hidden ./go 2076.0 ± 6.0 2065.0 2084.0 69.12 ± 0.77

See benchmarks documentation for more details.

Installation

Quick Install

Install the latest release on Linux (x86/x64 with glibc) or macOS (Intel/Apple Silicon):

curl --proto '=https' --tlsv1.2 -fsSL https://raw.githubusercontent.com/gregl83/paq/main/install.sh | sh

Installs to ~/.local/bin; add it to your PATH if needed.

Cargo

With the Rust toolchain installed:

cargo install paq

Download prebuilt binaries for Windows, macOS, and Linux, or see the installation guide for manual downloads, Nix, and installer options.

Bindings and Integrations

Use paq for BLAKE3 directory and file hashing in other languages and build tools:

Usage

Command Line Interface executable or Crate library.

Included in this repository is an example directory containing some sample files, a subdirectory and a symlink to test paq functionality.

Executable

Run paq [src] to hash source file or directory.

Output hash to .paq file as valid JSON.

For help, run paq --help.

Hash Example Directory

paq ./example

Path to example directory can be relative or absolute.

Use -i / --ignore-hidden to omit hidden entries.

Use -L / --follow to hash symbolic-link targets and traverse linked directories, including targets outside the source tree. Broken links and cycles return an error. Link following defaults to false: links are hashed by their target-path text, including when the source itself is a symbolic link. These options can change the resulting hash.

Crate Library

Add paq to project dependencies in Cargo.toml.

hash_source hashes a file or directory, with options to ignore hidden entries and follow symbolic links. Errors are returned as paq::Error.

Use Library

use paq;

fn main() -> Result<(), paq::Error> {
    let source = std::path::PathBuf::from("/path/to/source");
    let ignore_hidden = true; // .dir or .file
    let follow_links = false;
    let source_hash = paq::hash_source(&source, ignore_hidden, follow_links)?;

    println!("{}", source_hash);
    Ok(())
}

Content Limitations

Files must remain unchanged during hashing; modifying memory-mapped files can cause undefined behavior, including crashes.

Hashes are generated using file system content as input data to the BLAKE3 hashing algorithm.

By design, paq does NOT include file system metadata in hash input such as:

  • File modes
  • File ownership
  • File modification and access times
  • File ACLs and extended attributes
  • Hard links
  • Symlink target contents unless --follow is enabled (otherwise the target path is hashed)

Additionally, files or directory contents starting with dot or full stop can optionally be ignored.

How it Works

  1. Stream & Hash: Recursively discovers source system path(s) and hashes them in a parallel pipeline.
  2. Sort: Orders the hashes to ensure a deterministic output.
  3. Finalize: Computes the final hash by hashing the list of hashes.

Each entry hashes its relative path, a NUL byte (0x00), a type byte, and its payload. The NUL and type bytes are passed to the hasher together. Type bytes are 0x01 for files, 0x02 for directories, 0x03 for symlinks, and 0x04 for other filesystem entries. File payloads are contents; symlink payloads are target paths. Directories and other entries have no payload. Paths use / separators on Windows.

License

MIT

Releases

Used by

Contributors

Languages