Andrew Mercer
on this page

Common options

Option Meaning
-a archive mode: recursive and preserves permissions, owner, group, times, symlinks (-rlptgoD)
-v verbose (-vv for more)
-z compress during transfer (helps on slow links, hurts on fast LANs and already-compressed data)
-P --partial --progress: keep partial files and show progress
--delete remove files in the destination that are not in the source
--delete-before delete before transferring (useful when the destination is nearly full)
--ignore-existing skip files that already exist at the destination
-n / --dry-run show what would happen without doing it
-H preserve hard links
--bwlimit=KBPS limit bandwidth (for example --bwlimit=5000 is about 5 MB/s)
--remove-source-files delete each source file after it is transferred
--info=progress2 one overall progress line

Trailing slash matters: rsync -a src/ dst/ copies the contents of src into dst. rsync -a src dst/ creates dst/src.

Basic examples

# Simple sync with a log
rsync -a /source/directory/ /destination/directory/ >> /var/log/rsync.log

# Mirror: destination becomes an exact copy (removes extra files there). Test with -n first!
rsync -an --delete /source/directory/ /destination/directory/
rsync -a --delete /source/directory/ /destination/directory/

# Preview
rsync -avn /source/ /destination/

--delete with a mistyped destination can erase data. Always dry-run it first.

Over SSH

rsync -a -e ssh /local/dir/ [email protected]:/path/to/dest/          # push
rsync -avzP -e ssh [email protected]:/etc/ ~/etc_backup/               # pull
rsync -avzP --safe-links -e ssh [email protected]:/home/user/etc ~/etc_rsync/

--safe-links ignores symlinks that point outside the transferred tree.

Exclusions

rsync -av --exclude 'Downloads' --exclude 'Music' --exclude '*.tmp' /home/user/ /mnt/backup/home/
rsync -av --exclude-from=/root/rsync_exclude.txt /home/user/ /mnt/backup/home/

rsync_exclude.txt holds one pattern per line (Downloads, Pictures, ...).

Transfer a list of directories

rsync -a --files-from=sources.txt / /mnt/backup/         # paths in sources.txt are relative to the base dir (/)
rsync -avz -e ssh Games Music Documents Pictures [email protected]:~

Move files (delete after copy)

rsync -avP --remove-source-files Downloads/ /mnt/media/Downloads/
# empty source directories are left behind:
find Downloads/ -type d -empty -delete

Pause and resume

Re-running the same command continues where it stopped. Adding --partial (or -P) keeps half-transferred files so large files resume rather than restart. Ctrl+Z / bg / fg also work.

Backup script for cron

#!/bin/bash
set -euo pipefail
logfile=/var/log/rsync-to-backuphost.log
{
  echo "==== Start: $(date +'%Y-%m-%dT%H:%M:%S%z')"
  ionice -c2 -n7 rsync -a --partial --exclude 'cache/' \
      -e "ssh -T -o Compression=no" /source/path/ [email protected]:/dest/path/
  echo "==== End:   $(date +'%Y-%m-%dT%H:%M:%S%z')"
} >> "$logfile" 2>&1

ionice (see ionice) keeps the job from starving other disk users. Old guides suggest the arcfour cipher for speed. It has been removed from OpenSSH, and modern AES-GCM/ChaCha20 are fast enough. Schedule with cron.

For an integrity-checked, versioned backup consider borg/restic. rsync copies faithfully, including mistakes and ransomware-encrypted files, unless you keep dated snapshots (--link-dest).