Directory synchronization tool using checksums
Project description
Dubler
Directory synchronization tool.
Note: The name "dubler" comes from Polish, where it means "a person replacing an actor in film or theater" (stunt double / stand-in). Just as a dubler stands in for an actor, this tool creates backup copies that can stand in for your original files — if something happens to the original, the backup is ready to take its place.
Features
- Checksum-based comparison: Files are compared using SHA256 hashes
- Multiple destinations: Sync to multiple directories at once
- Idempotent: Running multiple times is safe - only copies missing or changed files
- Failure tracking: Tracks failed files and allows re-running
- Dry run mode: Preview changes before copying
- JSON configuration: Store sync settings in a config file
- Zero dependencies: Uses Python standard library only
Installation
No installation required! You can run dubler directly with uvx:
uvx dubler --help
If you prefer to install:
# From PyPI
pip install dubler
# or with uv
uv pip install dubler
# From source
uv install
Usage
Command Line
# Basic sync
uvx dubler --source /path/to/source --dest /path/to/dest1 --dest /path/to/dest2
# Dry run (preview without copying)
uvx dubler -s /path/to/source -d /path/to/dest --dry-run
# Verbose output
uvx dubler -s /path/to/source -d /path/to/dest -v
# Show failed files from previous runs
uvx dubler --failed
# Clear failed files from state
uvx dubler --clear-failed
Configuration File
Create a JSON config file (default: ~/.config/dubler/config.json):
{
"source": "/path/to/source",
"destinations": [
"/path/to/dest1",
"/path/to/dest2"
],
"dry_run": false,
"verbose": false
}
Then run without arguments:
uvx dubler
Or specify a custom config file:
uvx dubler --config /path/to/config.json
How It Works
- Scans the source directory recursively
- For each destination:
- Compares files using SHA256 checksums
- Copies files that don't exist or have different checksums
- Tracks any failures in
~/.local/state/dubler/state.json
- Displays summary of copied, skipped, and failed files
State
The application stores data in standard XDG Base Directory locations:
~/.config/dubler/config.json: Configuration file (optional)~/.local/state/dubler/state.json: Failed files from previous runs
Examples
# Sync photos to multiple backup drives
uvx dubler -s ~/Pictures -d /Volumes/Backup1/Photos -d /Volumes/Backup2/Photos
# Preview what would be synced
uvx dubler -s ~/Documents -d ~/Backup/Documents --dry-run -v
# After a failed run, see what failed
uvx dubler --failed
# Fix the issue and run again (idempotent)
uvx dubler -s ~/Documents -d ~/Backup/Documents
Releasing
The project uses automatic versioning based on git tags via setuptools_scm.
Creating a Release
Use the release helper script:
# Bump patch version (bug fixes)
uv run python scripts/release.py patch
# Bump minor version (new features)
uv run python scripts/release.py minor
# Bump major version (breaking changes)
uv run python scripts/release.py major
# Or specify exact version
uv run python scripts/release.py patch --version 1.2.3
This will:
- Create and push a git tag (e.g.,
v1.0.0) - Trigger the GitHub Actions release workflow
- Automatically create a published release with:
- Release notes from commits
- Installation instructions
- Full changelog link
- Publish to PyPI
Manual Release (Alternative)
# Create and push tag manually
git tag v1.0.0
git push origin v1.0.0
Version Format
Tags must follow semantic versioning: vX.Y.Z
X= Major version (breaking changes)Y= Minor version (new features, backwards compatible)Z= Patch version (bug fixes, backwards compatible)
Conventional Commits
This project uses conventional commit messages. See AGENTS.md for guidelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dubler-1.3.0.tar.gz.
File metadata
- Download URL: dubler-1.3.0.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3f49820ba2d8bdf9c6f2606522b46343b03fae04bf210e8a597fac52693187e
|
|
| MD5 |
4a367473d729c0e5db48ede067ffad1b
|
|
| BLAKE2b-256 |
e6abb78915ae6b6498bab0bcd0013a293fcc120d50ee39450f693662184165f1
|
File details
Details for the file dubler-1.3.0-py3-none-any.whl.
File metadata
- Download URL: dubler-1.3.0-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47a6ec6c820e33cf15e1db18eca03b8c71545ff98de0407f70c7aa2533bb2a8c
|
|
| MD5 |
5ab38b61ea2b111979a674c06e300ace
|
|
| BLAKE2b-256 |
ba051817bd2d426f18b3724758e01dc8dd2ac688803baddca0d6256d3db9a7c4
|