sha256sum — Hash a file with SHA-256 in bash, zsh, fish, PowerShell, and cmd across all 5 shells
Equivalents in every shell
sha256sum file.binGNU coreutils binary. Output format `<64-hex>␣␣<filename>` (TWO spaces — first space is fixed, second is `*` for binary mode `-b` or ` ` for text mode `-t`). Output is **lowercase** hex. `--check` / `-c manifest.txt` reads `<hash> <name>` lines and prints `name: OK` / `FAILED`; `--quiet` suppresses OK lines for CI use. Exit `1` if any check fails, `0` if all pass.
sha256sum file.binSame external `sha256sum` from GNU coreutils on Linux — zsh has no shell builtin. macOS does NOT ship `sha256sum` (BSD coreutils omits it); use `shasum -a 256 file.bin` instead (Perl wrapper, same hex output) or `brew install coreutils` and call `gsha256sum`.
sha256sum file.binSame external binary. Fish exit-code idiom — `if sha256sum -c sums.txt --quiet; echo "all good"; else; echo "FAILED"; end` — reads cleaner than bash's `||` chain. Fish lacks process substitution `<()` so piping streams through `psub` for inline-check: `sha256sum -c (echo "<hash> file.bin" | psub)`.
Get-FileHash file.bin -Algorithm SHA256Returns a `[Microsoft.PowerShell.Commands.FileHashInfo]` object with `Algorithm` / `Hash` / `Path` properties. `-Algorithm` defaults to `SHA256` since pwsh 4 — explicit is clearer. `Hash` is **UPPERCASE** hex (opposite of `sha256sum`!) — normalize with `.Hash.ToLower()` when comparing across tools. To match the `*sum` manifest format: `"{0} {1}" -f $h.Hash.ToLower(), (Split-Path $h.Path -Leaf)`.
certutil -hashfile file.bin SHA256Built into Windows since Vista. Output is verbose THREE lines: a header (`SHA256 hash of file.bin:`), the hash itself (uppercase, possibly with spaces every few chars on older Windows), and a trailing `CertUtil: -hashfile command completed successfully.`. Parse with `for /f "skip=1 tokens=*" %i in ('certutil -hashfile file.bin SHA256 ^| findstr /v ":"') do @echo %i` — skips the header + trailer + any line containing `:`.
Worked examples
Hash one file and print just the hash (strip filename + newline)
sha256sum file.bin | cut -d' ' -f1sha256sum file.bin | cut -d' ' -f1(Get-FileHash file.bin -Algorithm SHA256).Hash.ToLower()for /f "skip=1 tokens=1" %i in ('certutil -hashfile file.bin SHA256 ^| findstr /v ":"') do @echo %iGenerate a manifest of SHA-256 hashes for every file in a directory, then verify it later
sha256sum *.bin > SHA256SUMS && sha256sum -c SHA256SUMSGet-ChildItem *.bin | Get-FileHash -Algorithm SHA256 | ForEach-Object { "{0} {1}" -f $_.Hash.ToLower(), (Split-Path $_.Path -Leaf) } > SHA256SUMS # then verify by re-hashing and diffingHash data from stdin (no file involved)
echo -n "hello" | sha256sum$s = [Text.Encoding]::UTF8.GetBytes("hello"); $sha = [Security.Cryptography.SHA256]::Create(); [BitConverter]::ToString($sha.ComputeHash($s)).Replace("-","").ToLower()echo|set /p="hello" > tmp.txt && certutil -hashfile tmp.txt SHA256 && del tmp.txtGotchas
- Trailing-newline trap: `echo "hello" | sha256sum` is NOT the same as `printf hello | sha256sum`. `echo` appends `\n`, `printf` does not, so the two produce different hashes. For deterministic hashing of literal strings, always use `printf` (or `echo -n` on Linux, but `echo -n` on macOS prints the literal `-n` — non-portable). To hash a file CONTENT without its trailing newline ambiguity, hash the file directly: `sha256sum file.txt`, not `cat file.txt | sha256sum` (identical only if the file ends without an extra newline).
- GNU `sha256sum` outputs **lowercase** hex; pwsh `Get-FileHash` outputs **UPPERCASE** hex; cmd `certutil` outputs **uppercase** (sometimes with embedded spaces on older Win versions). Cross-tool string-compare on `==` will report identical-content files as different unless you normalize with `.ToLower()` (pwsh) or `tr A-Z a-z` (bash). The bytes are the same; only the rendered text differs.
- The TWO-space separator in `sha256sum` output is load-bearing — `sha256sum -c` parses lines as `<hash>␣<mode-marker>␣<filename>` where mode-marker is `*` for binary or space for text. Anything that munges that separator (Windows line endings, an editor that re-indents the manifest, `sed -i 's/ / /g'`) breaks `-c` verification with `improperly formatted SHA256 checksum line`. Keep manifest files in LF mode (`.gitattributes` `* -text` for binary files in repos).
- macOS DOES NOT ship `sha256sum` — only BSD `shasum` (a Perl wrapper). Scripts that call `sha256sum` directly break on macOS unless you `brew install coreutils` (which installs as `gsha256sum`) or branch on `uname`: `if command -v sha256sum; then sha256sum f; else shasum -a 256 f; fi`. The hash itself is bit-identical across implementations — only the binary name differs.
- pwsh `Get-FileHash` reads the file in one pass with FIPS-validated `System.Security.Cryptography.SHA256` (hardware-accelerated SHA-NI on x86_64 / ARM crypto extensions when available) — typically 1–3× faster than GNU `sha256sum` on the same hardware. For multi-GB files, pwsh wins. For shell-script integration / manifest verification, `sha256sum -c` is the only cross-Unix idiom.