| Crates.io | czkawka-dupes-to-symlinks |
| lib.rs | czkawka-dupes-to-symlinks |
| version | 0.1.1 |
| created_at | 2025-11-09 06:34:31.302553+00 |
| updated_at | 2025-11-09 08:12:59.486594+00 |
| description | Safely turn Czkawka duplicate reports into space-saving symlinks |
| homepage | https://github.com/KnotFalse/czkawka-dupes-to-symlinks |
| repository | https://github.com/KnotFalse/czkawka-dupes-to-symlinks |
| max_upload_size | |
| id | 1923722 |
| size | 107,128 |
A careful CLI for reclaiming disk space by turning duplicate files into symlinks.
This project started as a companion for Czkawka's czkawka_cli JSON duplicate reports, but it works with any JSON document that matches the schema enforced below. If you produce the same structure from another tool, this binary will happily deduplicate it.
--allow-root directories so the tool never touches unexpected paths.# Install from crates.io
cargo install czkawka-dupes-to-symlinks
# (Optional) install from a local checkout
cargo install --path .
# Run against a Czkawka JSON export
czkawka-dupes-to-symlinks \
--input-file-path ~/czkawka_duplicates.json \
--allow-root /srv/media --allow-root /srv/backups
Add --dry-run to preview actions without touching the filesystem.
Planning ahead: Once we publish prebuilt archives you will also be able to use
cargo binstall czkawka-dupes-to-symlinksfor instant installs.
cargo install czkawka-dupes-to-symlinks – preferred path once the crate is on crates.io.cargo binstall czkawka-dupes-to-symlinks – fast installs from GitHub Release artifacts (after the first tagged release ships).cargo install --git https://github.com/KnotFalse/czkawka-dupes-to-symlinks – grab the latest main branch without waiting for a release.$PATH.| Exit Code | Meaning | Typical Cause |
|---|---|---|
0 |
Every duplicate was processed and/or skipped intentionally | Happy path or dry-run |
1 |
One or more duplicates could not be processed | Missing files, symlink permission errors, outside allow-root, invalid JSON |
| Flag | Description |
|---|---|
-i, --input-file-path <PATH> |
Path to a JSON file or directory of JSON files to process |
-a, --allow-root <PATH> (repeatable, required) |
Directories that the tool is allowed to modify. Paths are canonicalized and enforced for every duplicate |
-d, --dry-run |
Log replacements without touching the filesystem |
-o, --original-to-keep <first|last|oldest|newest> |
Strategy for choosing the canonical copy (default newest) |
Any producer that emits the following structure can be consumed.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Czkawka Duplicates Report",
"description": "Schema for duplicate groups keyed by file size.",
"type": "object",
"propertyNames": {
"description": "Decimal representation of the file size in bytes.",
"pattern": "^[0-9]+$"
},
"additionalProperties": {
"description": "A list of groups, each containing files with identical hashes.",
"type": "array",
"items": {
"description": "Files that share the same hash.",
"type": "array",
"minItems": 2,
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": { "type": "string" },
"modified_date": { "type": "integer", "minimum": 0 },
"size": { "type": "integer", "minimum": 0 },
"hash": { "type": "string" }
},
"required": ["path", "modified_date", "size", "hash"]
}
}
}
}
A minimal example:
{
"8229": [[
{
"path": "/var/www/uploads/a.jpg",
"modified_date": 1724175436,
"size": 8229,
"hash": "a5b042..."
},
{
"path": "/var/www/uploads/b.jpg",
"modified_date": 1724175383,
"size": 8229,
"hash": "a5b042..."
}
]]
}
--allow-root directories.*.czkawka-bak[-N]# Format + lint
cargo fmt && cargo clippy --all-targets --all-features
# Run regression tests (includes integration tests in tests/safety.rs)
cargo test
The integration tests spin up temporary directories with real files, so they work on macOS, Linux, and Windows.
--allow-root paths must already exist; canonicalization will fail otherwise.--allow-root at least once and that paths don’t expand to blank strings (quote shell globs).--allow-root.std::os::windows::fs::symlink_file can create links.Dual-licensed under Apache 2.0 or MIT. Pick the one that works for you.