rsync: copy and synchronise files

Updated November 2026

rsync copies files and directories, locally or between machines over SSH. On the second run it transfers only what changed, which makes it the standard tool for mirrors, deployments and backups.

rsync [options] source ... destination rsync [options] source user@host:destination

The options you need

OptionMeaning
-aArchive: recursive, keep permissions, times, links, owners (as root)
-vShow files as they are transferred
-hHuman-readable numbers
-zCompress during transfer (useful on slow links)
-n, --dry-runShow what would happen, change nothing
--deleteDelete files at the destination that no longer exist at the source
--exclude=PATTERNSkip matching files
-PShow progress and keep partial files so a transfer can resume
-HAXAlso keep hard links, ACLs and extended attributes

Examples

rsync -avh ~/Documents/ /mnt/usb/Documents/              # local copy
rsync -avhP bigfile.iso user@server:/srv/iso/            # to a server, resumable
rsync -avh user@server:/var/www/site/ ./site-backup/     # from a server
rsync -avh --delete ./public/ deploy@web1:/var/www/site/ # make the target an exact mirror
rsync -avhn --delete ./public/ deploy@web1:/var/www/site/   # dry run of the same
rsync -avh --exclude='.git' --exclude='*.tmp' src/ dest/
rsync -avh -e 'ssh -p 2222' data/ user@host:/data/       # SSH on another port
rsync -avh --bwlimit=10m data/ backup:/data/             # limit to 10 MB/s

The trailing slash rule

A slash at the end of the source changes the result:

Both end in the same place here, but mixing them up (rsync -a photos /backup/photos/) gives you /backup/photos/photos. When the source is a directory, a slash on the destination makes no difference. When copying a single file to a path that does not exist, a trailing slash makes rsync create a directory of that name.

Always dry-run --delete

With --delete, a wrong source path can make rsync delete everything at the destination. Run with -n first and read the "deleting" lines.

Simple snapshot backups

With --link-dest, files that did not change since the last backup become hard links to the previous copy. Each backup looks complete but uses space only for changed files:

today=$(date +%F)
rsync -a --delete --link-dest=/backup/latest /home/ /backup/$today/
ln -sfn /backup/$today /backup/latest

Run it nightly from crontab. For encrypted, deduplicated backups to remote storage, look at restic or BorgBackup.

Things to know