OPEN-SOURCE FILE INTEGRITY

Know your files are still your files.

Bit Backup records SHA-512 fingerprints in a local database and checks them again over time, helping you spot silent corruption in the files you keep.

Local by design MIT licensed Built with C++23

Built for the long view
  • SHA-512
  • SQLite
  • C++23
  • MIT License

01 / THE IDEA

A record you can check against.

Files can change without an obvious warning. Bit Backup gives you a local reference point, then compares future scans with that record.

01

Establish a baseline

Scan a directory. Bit Backup calculates file hashes and saves metadata in a local SQLite database.

02

Return and verify

Run it again to compare file contents with the stored record. A full check rehashes files, including those with unchanged modification times.

03

Investigate changes

See detected corruption and lock violations in the terminal, with optional CSV reports for a closer look.

02 / THE TOOLKIT

The right check for the moment.

Start with a complete verification. For large collections, choose how much work each later run should do.

01 / VERIFY

Check every byte

The default full check rehashes files, so corruption can be found even when modification times have not changed.

DEFAULT MODE
02 / SCALE

Work at your pace

Use a quick scan or a rotating scrub for large collections. Automatic worker selection adapts to the detected storage type on Linux.

QUICK · SCRUB · THREADS
03 / FREEZE

Protect archived trees

Add a .bitbackuplock marker after indexing to keep a directory’s saved state fixed and report additions, edits, or deletions.

DIRECTORY LOCKING
04 / FOCUS

Keep the signal clear

Exclude paths with .bitbackupignore, export CSV reports and a full file index, and verify the local database with its own checksum.

IGNORE RULES · CSV

A check is not a copy. Bit Backup verifies integrity; it does not create or restore backups. Keep separate copies of important files.

03 / RUN MODES

Three ways to check your files.

Use a full check for complete coverage on each run, or select how much unchanged data to revisit. Examples assume you have set BIT_BACKUP as shown in Get started and are inside the data directory.

01 / DEFAULTFULL

Full verification

Hashes every tracked file on each run. If file contents change while the modification time stays the same, the changed hash is reported as bit rot.

Run
"$BIT_BACKUP"

Equivalent to "$BIT_BACKUP" check or "$BIT_BACKUP" check scrub=100.

02 / FASTESTQUICK

Quick scan

Hashes new files and files whose modification times changed. It usually skips unchanged-time files, so previously unknown silent corruption in those files is not detected on this run.

Run
"$BIT_BACKUP" check quick=true

Equivalent to scrub=0. Locked files and files already marked corrupt are still verified.

03 / ROTATINGSCRUB

Partial scrub

Selects the oldest share of stored records for rehashing, while also hashing new and changed-time files. Repeated runs rotate coverage through the collection.

Run
"$BIT_BACKUP" check scrub=25

Choose any percentage from 0 to 100. A positive percentage rounds up to at least one previously indexed file. A 25% scrub does not check every file on that run.

How modes interact

quick=true takes priority over scrub=N and makes it a 0% scrub. Locked files and files already marked corrupt are always hashed. In unlocked directories, a changed modification time is treated as an ordinary edit and its new hash becomes the saved baseline.

04 / CLI REFERENCE

Every check option, explained.

Put options after the explicit check command, separated by spaces: "$BIT_BACKUP" check key=value. Running the executable with no arguments performs a default full check of the current directory. Unknown options and invalid values produce an error.

All check command options, values, defaults and effects
OptionValueDefaultWhat it does
dirAbsolute or relative pathCurrent directoryChooses the directory to scan and where the local database and reports are stored. Relative paths are resolved from the shell’s working directory.
quicktrue or falsefalseWith true, skips rehashing unchanged-time, unlocked files unless already marked corrupt. It overrides scrub to 0%.
scrub0–100100Selects the oldest N% of stored records for rehashing, rounding up to at least one file when N is positive. 0 is quick behavior; 100 is a full check.
threads1–16AutomaticSets hashing workers manually. On Linux, automatic selection uses 1 for HDD or unknown storage, up to 4 for SSD and up to 16 for NVMe, bounded by available CPUs.
reporttrue or falsefalseWith true, writes .bitbackupreport.csv for detected bit rot. Lock violations are reported in the terminal, not this CSV.
verbosetrue or falsefalsePrints more detailed scan information, including file listings.
bitbackupindextrue or falsefalseWith true, writes .bitbackupindex.csv containing each included file’s relative path, size in bytes, and SHA-512 hash.
confirmdeleteOffInteractively asks whether to remove each deleted locked file from the stored database. It does not confirm modified or newly added files.

Directory paths. dir=/path/to/data selects a collection regardless of the shell’s current directory. Bit Backup writes its metadata and requested CSV files into the selected directory.

Index cost. An index run hashes every included file to produce its SHA-512 column. This extra read happens even with quick=true or a partial scrub.

EXAMPLE COMMANDS

Combine options to suit the job.

The commands below use the executable path set during the build steps.

Detailed full check

"$BIT_BACKUP" check verbose=true report=true

Rehash every file, print detailed progress, and write a CSV report of any bit rot.

Bounded routine scan

"$BIT_BACKUP" check scrub=20 threads=8

Recheck the oldest 20% of unchanged-time files with eight hashing workers.

Resolve a locked deletion

"$BIT_BACKUP" check confirm=delete

After a locked file is deleted, answer each prompt to keep its violation or remove its saved row.

Target a directory

"$BIT_BACKUP" check dir=/path/to/data report=true

Scan a chosen path from elsewhere. Both the bit-rot report and integrity database are written into that directory.

Export a file index

"$BIT_BACKUP" check bitbackupindex=true

Create .bitbackupindex.csv with relative path, byte size and current SHA-512 hash for each included file.

Ask the CLI

"$BIT_BACKUP" help
"$BIT_BACKUP" version

Show the built-in usage text or the current version string without running a file check.

05 / IN PRACTICE

What happens around a check.

A few operational details help you interpret the result and keep your baseline useful.

01 / BASELINE

New and edited files

The first run records hashes. Later runs add new files and update the stored hash of an unlocked file whose modification time changed. Bit rot is flagged when a full or partial check finds different content with an unchanged modification time.

02 / LOCKING

Freeze a directory

Index the files first, then add an empty .bitbackuplock file in the directory to freeze it. Subsequent runs keep saved hashes and timestamps fixed, and report modified, new, or deleted files in that subtree. Remove the marker to resume normal updates.

touch archive/.bitbackuplock
"$BIT_BACKUP" check
03 / IGNORE RULES

Scan only what matters

Place .bitbackupignore in the scanned root. Patterns support *, ?, root-anchored paths such as /logs/, directory rules ending in /, and ! to re-include a path. Bit Backup metadata remains excluded even with a ! rule. Only the root ignore file is loaded.

/logs/
*.tmp
!important.tmp
04 / OUTPUT

Read the result

The directory holds .bitbackup.sqlite3 and its .sha512 checksum. report=true adds a CSV for bit rot. A check exits with a nonzero code when it detects bit rot or a lock violation, making it usable in scripts.

06 / GET STARTED

Make your first baseline.

Build from source, move into the directory you want to monitor, and run your first check. Later runs compare against the local record.

YOU'LL NEED

A C++23 compiler, CMake 3.25+, OpenSSL, and SQLite3. The SQLiteCpp dependency is included as a Git submodule.

Read the full documentation
01 — BUILD & RUN
git clone --recurse-submodules https://github.com/robertvokac/bit-backup.git
cd bit-backup
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
BIT_BACKUP="$PWD/build/bit_backup"
cd /path/to/data
"$BIT_BACKUP"

Replace /path/to/data with your directory. By default, bit_backup checks the current directory. Run it again later to verify the saved baseline.