Rsync Command Builder
Build copy-ready rsync commands for local copies, remote (SSH) transfers and incremental
backups — without memorising the flag soup or trusting a half-broken forum snippet. Pick a starting
direction (local copy, push to a server, pull from a server, or remote-to-remote), fill in your paths,
and toggle the options that matter: --delete mirroring with its safety nets,
--link-dest snapshot rotation for daily backups, bandwidth limits, resume-safe transfers.
Every option is explained in plain English, the live preview shows exactly what will run, and the
validation panel catches the mistakes that actually destroy data — a --delete without a
dry run, a folder being copied into itself, or --link-dest pointed at the destination.
Already have a command you don’t understand? Paste it into the import panel and it gets broken
back into its flags for you. Everything happens in your browser.
1 · Starting point
Pick a direction to fill the form with a working baseline. Choosing a preset replaces the current command — everything can be edited afterwards.
2 · Source and destination
3 · Options
4 · Include / exclude patterns (optional)
Filter what gets synced using rsync filter syntax (*, ?, [seq]; a leading / anchors to the transfer root). Rules apply in order — first match wins, so put specific includes before broad excludes. e.g. exclude *.tmp, or sync only images with include *.jpg + exclude *.
5 · Paste an existing rsync command (optional)
Have a command you inherited and don’t fully understand? Paste it here — flags, SSH options and patterns are mapped into the form above so you can inspect and change each part. Options this builder doesn’t offer are kept as-is and reported.
6 · Your rsync command
What this does
Validation
Run it safely
The exported script always runs a --dry-run first — review what would change, then run the real thing. That two-step habit is what separates a backup you trust from a lesson you learn at 2 am.
The trailing slash rule — the #1 rsync mistake
Whether a path ends in / completely changes what gets copied. rsync /a/b/ /c/ copies the contents of b into c; rsync /a/b /c/ copies the folder b itself, so you end up with /c/b/. The live hints under each path field above tell you which mode you’re in as you type.
| Command | Result |
|---|---|
| rsync /a/b/ /c/ | Contents of b land directly in /c (files at /c/file.txt). |
| rsync /a/b /c/ | The folder itself is copied — files end up at /c/b/file.txt. |
| rsync /a/b/ /c/d | Contents of b land in /c/d — rsync creates d for you. |
| rsync /a/b /c/d | Folder b is copied into /c/d/b/. |
The same rule applies to the remote side: user@host:/path/ (contents) vs user@host:/path (the folder). When in doubt, end both paths with a slash and think in terms of “contents into contents”.
How rsync decides what to copy
By default rsync compares each file’s size and modification time. If both match, the file is skipped — that’s why the second run of a 1 TB backup finishes in seconds while the first takes hours. This is also its blind spot: a file that was modified but restored to its original timestamp (or received with -t from another sync) looks unchanged.
- --checksum hashes both sides instead — slower, but it catches timestamp tricks. Use it once after a power cut or a copy from a filesystem that doesn’t store times well (FAT).
- -P keeps partially transferred files, so an interrupted 40 GB transfer resumes instead of restarting.
- --link-dest is the incremental-backup trick: point it at yesterday’s snapshot and unchanged files become hard links (same inode, zero extra space) while changed files are copied fresh. Each daily snapshot stays a complete, independent copy — delete one and the rest survive.
Flag reference
| Flag | What it does | When to use it |
|---|---|---|
| -a | Archive: recursive + preserve permissions, times, symlinks, hard links, group/owner. | Almost always — it’s the baseline for backups and deploys alike. |
| -v | Log each transferred file. | First runs, and anything you’re unsure about. |
| -z | Compress data in transit. | Internet links and text-heavy trees. Skip for fast LANs and media files. |
| -P | --partial + --progress: resume interrupted transfers with a progress meter. | Anything large over anything less than a wired LAN. |
| --checksum | Compare by content hash instead of size + time. | After power cuts, or sources with unreliable timestamps. |
| --itemize-changes | Per-file change codes (what changed, why). | Auditing a sync — pairs well with --dry-run. |
| --dry-run | Show what would happen without changing anything. | Every new command, before every --delete run. |
| --delete | Remove destination files missing from the source (true mirroring). | Deploy targets and snapshot rotations — never on a one-off copy you’re unsure about. |
| --max-delete=N | Cap how many files --delete may remove. | First mirror runs — if the cap is hit, something is wrong and rsync stops instead of deleting everything. |
| --delete-exclude=P | Protect matching files from --delete. | Secrets, local configs and anything the destination must keep even when absent from the source. |
| --bwlimit=KB/s | Caps transfer speed (in KB/s, not MB/s). | Overnight backups on a home connection you still need in the morning. |
| --one-filesystem | Don’t cross mount points. | Sources with mounted USB/NAS volumes you don’t want dragged in. |
| --link-dest=DIR | Hard-link unchanged files from a previous snapshot. | Daily/weekly rotation backups — full copies at incremental cost. |
| --backup-dir=DIR | Move overwritten/removed destination files to DIR (implies --backup). | When “the old version” must survive a sync. |
| --remove-source-files | Delete source files after a successful transfer (move semantics). | Draining a camera card or log spool — the destination is the only copy afterwards. |
| --stats | Summary of files, bytes and speed at the end. | Cron jobs you want a line of evidence from. |
Automate it on a Pi
The classic setup: a daily snapshot with hard-linked rotation, run from cron. Each run makes a complete copy of the day; unchanged files cost nothing because they’re hard links to yesterday’s inodes.
# /usr/local/bin/pi-backup.sh
#!/bin/sh
TODAY=$(date +%F)
PREV=$(date -d yesterday +%F)
DEST=/mnt/backups/data-$TODAY
mkdir -p "$DEST"
rsync -a --delete --stats \
--link-dest="/mnt/backups/data-$PREV" \
/home/pi/data/ "$DEST/"
# keep the last 14 snapshots, prune the rest
ls -1d /mnt/backups/data-* | sort | head -n -14 | xargs -r rm -rfThen one cron line (cron -e, running as your user — note the escaped %, which cron would otherwise treat as a newline):
30 2 * * * /usr/local/bin/pi-backup.sh >> /home/pi/backups.log 2>&1
Build the rsync line above with this tool first (the Incremental snapshot preset) and run it by hand a couple of times before letting cron take over.
Related tools
Suggested
Luke Keam | techgeek.biz