Use rsync Safely for Copies, Backups and Remote Transfers
One missing slash and rsync copies the folder instead of its contents; one stray --delete and it wipes files from your backup. In about 10 minutes you will preview, run and check a repeatable rsync copy, and learn to spot the options that delete or overwrite data.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use rsync 3.2.7, protocol version 31.
Before you start
- Rsync on both ends. The sending and receiving machines both need it.
- A login for remote transfers. An account on the other host, normally over SSH.
- Two machines at most. Rsync does not copy between two remote hosts in one command.
- Time to read the preview. Allow for it before any real transfer.
The commands below use ordinary user permissions and harmless paths under /tmp. Use sudo only when the destination is owned by another account or the transfer must preserve privileged metadata. A copy being remote is not a reason to add sudo.
1. Check the installed version
Find out what the machine running the command can actually do:
rsync --version
Checkpoint
On this installation the first line is:
rsync version 3.2.7 protocol version 31
The same output lists compiled-in features and the checksum and compression choices. Remote transfers negotiate with the other rsync, so the remote machine may support fewer options.
2. Preview before changing anything
Make a small source tree and ask rsync what it would do.
-nor--dry-runmakes no changes.-iitemises changes.-vnames transferred files.
mkdir -p /tmp/rsync-demo/source /tmp/rsync-demo/destination
printf 'draft\n' > /tmp/rsync-demo/source/notes.txt
rsync -avni /tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
Expect an itemised line for notes.txt, then a summary similar to:
>f+++++++++ notes.txt
sent ... bytes received ... bytes ... bytes/sec
total size is 6 speedup is ...
Byte counts and speed depend on the build. If the preview lists an unexpected top-level directory, stop and fix the source or destination path before you remove the n.
Checkpoint
A dry run describes the intended files and leaves the destination unchanged. Confirm it: the find below should list nothing yet.
find /tmp/rsync-demo/destination -maxdepth 1 -type f -print
3. Copy a directory and mind the slash
Archive mode, -a, is the general-purpose directory copy.
- What it includes: recursion, links, permissions, modification times, group, owner, and device or special files, where the account and platform permit.
- What it leaves out: ACLs, extended attributes, access times, create times and hard links. Add those deliberately when you need them.
rsync -ai /tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
The trailing slash on source/ means "copy the contents". Leave it off and rsync copies the directory itself beneath the destination:
rsync -ai /tmp/rsync-demo/source /tmp/rsync-demo/with-directory/
Checkpoint
The first destination now holds notes.txt; the second holds source/notes.txt.
Warning
This is the most common rsync mistake, especially when a script assembles the destination path.
Run the same command again with -n. If nothing changed, no itemised file should appear:
rsync -ani /tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
4. Transfer over SSH
A single colon after a host selects the remote-shell transport. Pull a remote directory into a local backup:
rsync -av --dry-run USER@HOST:/srv/example/ /tmp/example-backup/
Replace USER, HOST and the paths with values you have permission to use. The remote machine must have rsync installed. A push is the same syntax with the local source first:
rsync -av --dry-run /srv/example/ USER@HOST:/srv/example-backup/
- Another remote shell: rsync normally uses SSH here, but
-eselects something else, for example-e 'ssh -p 2222'. Keep the shell quoting intact when the command has arguments. - Two colons means a daemon.
HOST::moduleand anrsync://URL talk to an rsync daemon instead. A daemon module has its own access rules and may need a password file. --password-fileis daemon-only. It does nothing for SSH, and rsync rejects a password file that is world-readable.
5. Select files without copying everything
Exclude caches and generated files with a pattern. Quote it so the shell does not expand it.
rsync -avni \
--exclude='*.cache' \
--exclude='build/' \
/tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
- Patterns act on the transfer file list.
- Need files beneath an excluded directory? Add matching include rules and test with
-vv, which shows why individual paths were included or excluded. - Fixed list of paths?
--files-from=FILEreads source names from a file. Check its format and the source root carefully before a backup job relies on it.
6. Treat deletion as a separate operation
Plain rsync creates and updates files but never removes destination files missing from the source. --delete changes that, and it can remove unrelated files from the destination. Treat it as destructive.
Warning
Never use --delete until a dry run shows exactly the deletions you expect. Keep a separate backup if the destination is valuable.
rsync -avni --delete /tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
- Read the
*deletinglines. Each one is a destination entry that would be removed. - Preview wrong? Drop
--deleteand fix the paths or filters. - Preview right? Run the same command without the
n. - Timing is not a safety net.
--delete-before,--delete-duringand--delete-afterschedule deletion differently; none makes it reversible.
Tip
Add --max-delete=NUMBER as a guardrail. Exit status 25 means the limit stopped further deletions. It does not replace a preview.
7. Keep a copy before overwriting
When replacing a file needs a local fallback, use --backup. Without --backup-dir, rsync appends ~ to the old file name. A dedicated directory is easier to inspect:
rsync -ai --backup --backup-dir=/tmp/rsync-demo/previous \
/tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
Warning
Do not put the backup directory inside the source tree when the command also deletes, unless you have a carefully tested filter.
Recovery
After an accidental replacement, stop the job, inspect the files in previous, and copy back the version you need with an ordinary rsync command. Do not blindly restore the whole directory.
8. Diagnose the result
--statsgives transfer totals.-Pkeeps partial files and shows per-file progress on a long transfer. It equals--partial --progress.--checksumcompares content when size and modification time cannot be trusted, at the cost of extra reading.
rsync -av --stats /tmp/rsync-demo/source/ /tmp/rsync-demo/destination/
Exit statuses worth knowing:
- 0: success.
- 23: partial transfer due to an error.
- 24: source files vanished during the scan.
- 25:
--max-deletestopped deletions. - 30: I/O timeout.
- 35: daemon connection timeout.
Treat any non-zero status as needing inspection, even if most files arrived.
Seeing "protocol version mismatch, is your shell clean?"? Check whether the remote shell prints startup text:
ssh USER@HOST /bin/true > /tmp/remote-shell-output
wc -c /tmp/remote-shell-output
Checkpoint
A working non-interactive shell produces a zero-byte file. Fix the shell startup output before retrying rsync.
Warning
Never hide a failed transfer by discarding stderr or by checking only whether the command printed filenames.
Done means
- Version checked for the installed rsync, and the remote one where relevant.
- Dry run inspected, both paths included, trailing slash on the source confirmed.
- Archive mode used knowingly, with ACL, xattr or hard-link options added only when needed.
- Every
--deletepreviewed, with a recovery copy of valuable data. - Exit status checked, and any non-zero result investigated.