rsync Cheat Sheet
These cover most copies, mirrors and backups:
rsync -av src/ dest/ # copy contents of src into dest, keep metadata
rsync -avn --delete src/ dest/ # dry run of an exact mirror
rsync -av --delete src/ dest/ # exact mirror (removes extra files in dest)
rsync -avz src/ user@host:/srv/backup/ # push over SSH with compression
rsync -avP user@host:/var/log/app/ ./logs/ # pull with progress + resumable partials
rsync -av --exclude='node_modules' proj/ /mnt/usb/proj/
Syntax: rsync [options] SRC... DEST. Either side can be remote (user@host:path), which uses SSH by default. rsync only sends the differences between source and destination, so a second run of the same command is fast. It is installed by default on most distros; otherwise sudo apt install rsync, sudo dnf install rsync, sudo pacman -S rsync or sudo zypper install rsync. Remote transfers need rsync installed on both machines.
rsync -a photos dest/ creates dest/photos/. rsync -a photos/ dest/ puts the files straight into dest/. Combined with --delete, the wrong one can wipe a directory. Run with -n first.
Core options
| Command | What it does |
|---|---|
rsync -a src/ dest/ | Archive mode: recursive, keeps permissions, times, symlinks, owner and group (owner needs root) |
rsync -av src/ dest/ | Same, listing every file transferred |
rsync -r src/ dest/ | Recursive only, without preserving metadata |
rsync -aH src/ dest/ | Also preserve hard links |
rsync -aAX src/ dest/ | Also preserve ACLs and extended attributes (SELinux labels, capabilities) |
rsync -aAXH --numeric-ids src/ dest/ | Full-fidelity system copy; keep UIDs/GIDs as numbers |
rsync -az src/ host:dest/ | Compress data in transit (helps on slow links, not on LAN) |
rsync -a --info=progress2 src/ dest/ | One overall progress line instead of per-file output |
rsync -aP src/ dest/ | -P = --partial --progress: per-file progress, keep partial files |
rsync -ah --stats src/ dest/ | Print a summary with human-readable sizes |
rsync -ai src/ dest/ | Itemize changes: shows why each file is sent |
Dry runs and comparing
| Command | What it does |
|---|---|
rsync -avn src/ dest/ | Dry run: show what would be copied, change nothing |
rsync -ain --delete src/ dest/ | Dry run of a mirror; lines starting *deleting would be removed |
rsync -avc src/ dest/ | Compare by checksum instead of size + time (slower, catches silent changes) |
rsync -avnc src/ dest/ | Verify a backup: list files whose content differs |
rsync -a --size-only src/ dest/ | Skip files with the same size, ignore timestamps |
rsync -a --modify-window=2 src/ /mnt/fat/ | Tolerate 2-second timestamp precision on FAT/exFAT drives |
Deleting and mirroring
| Command | What it does |
|---|---|
rsync -a --delete src/ dest/ | Delete files in dest that are not in src |
rsync -a --delete-after src/ dest/ | Delete after the transfer finishes (safer if the run is interrupted) |
rsync -a --delete-excluded src/ dest/ | Also delete files in dest that match your excludes |
rsync -a --delete --max-delete=50 src/ dest/ | Abort deletions after 50 files (guard against a wrong path) |
rsync -a --delete --backup --backup-dir=../old-$(date +%F) src/ dest/ | Move replaced and deleted files into a dated folder instead of losing them |
rsync -a --remove-source-files src/ dest/ | Move: delete source files after they are copied (directories stay) |
rsync -a --ignore-existing src/ dest/ | Never overwrite files that already exist in dest |
rsync -au src/ dest/ | Update: skip files that are newer in dest |
Remote transfers over SSH
| Command | What it does |
|---|---|
rsync -av src/ user@host:/path/ | Push local files to a remote host |
rsync -av user@host:/path/ dest/ | Pull remote files to the local machine |
rsync -av -e 'ssh -p 2222' src/ host:/path/ | Use a non-standard SSH port |
rsync -av -e 'ssh -i ~/.ssh/backup_ed25519' src/ host:/path/ | Use a specific key |
rsync -av host:'/path/with space/' dest/ | Quote remote paths that contain spaces |
rsync -av --rsync-path='sudo rsync' src/ host:/etc/app/ | Run rsync as root on the remote side (needs passwordless sudo for rsync) |
rsync -av --bwlimit=5m src/ host:/path/ | Limit bandwidth to about 5 MB/s |
rsync -av --mkpath src/ host:/new/deep/path/ | Create missing destination directories (rsync 3.2.3+) |
rsync -av host1:/a/ host2:/b/ | Not supported: one side must be local. Run rsync on one of the hosts instead. |
Key-based login makes unattended rsync jobs possible; set it up with the SSH keys guide. More SSH options are in the ssh cheat sheet.
Include and exclude filters
| Command | What it does |
|---|---|
--exclude='*.tmp' | Skip files matching a pattern anywhere in the tree |
--exclude='/cache/' | Leading / anchors to the top of the source; trailing / matches directories only |
--exclude={'.git','node_modules','*.log'} | Several excludes via bash brace expansion |
--exclude-from=excludes.txt | Read patterns from a file, one per line |
--include='*/' --include='*.jpg' --exclude='*' | Copy only .jpg files but keep the directory structure (order matters) |
-m (--prune-empty-dirs) | Drop directories that end up empty after filtering |
-C (--cvs-exclude) | Skip VCS directories (.git, .svn, .hg) and build junk such as *.o and *~ |
--files-from=list.txt | Copy only the paths listed in a file (relative to the source) |
--max-size=100m / --min-size=1k | Skip files above or below a size |
Common recipes
Back up your home directory to a USB drive, skipping caches. The full script with logging is at rsync home backup script:
rsync -aAXh --delete --info=progress2 \
--exclude={'.cache','Downloads','.local/share/Trash'} \
~/ /media/$USER/backup/home/
Snapshot-style incremental backups where unchanged files are hard links to the previous run:
today=$(date +%F)
rsync -a --delete --link-dest=/backup/latest ~/ /backup/$today/
ln -sfn /backup/$today /backup/latest
Copy a whole system to a new disk (run from a live USB, both mounted):
sudo rsync -aAXHv --numeric-ids \
--exclude={'/dev/*','/proc/*','/sys/*','/tmp/*','/run/*','/mnt/*','/media/*','/lost+found'} \
/mnt/old/ /mnt/new/
Deploy a static site and only upload what changed:
rsync -avz --delete --exclude='.git' public/ deploy@web1:/var/www/site/
Resume a huge file over a flaky connection:
rsync -avP --append-verify bigfile.iso user@host:/data/
Check how much will be transferred before starting (compare to free space with du and df):
rsync -an --stats src/ dest/ | grep -E 'Number of regular files transferred|Total transferred file size'
Gotchas
- Trailing slash on the source.
src/means "the contents of src". The slash on the destination does not matter. --deleteplus a wrong path is destructive. Always do a-nrun first, and consider--max-deleteor--backup-dirin scheduled jobs.- Owners are only kept as root. As a normal user,
-asilently sets you as the owner on the destination. Usesudo rsyncfor system files, and--numeric-idswhen the user names differ between machines. - FAT, exFAT and NTFS drives cannot store Linux permissions. You get errors like
chown failed: Operation not permitted. Use-rltvinstead of-a, and--modify-window=2for FAT. See Operation not permitted. -zon a fast LAN slows things down because the CPU becomes the bottleneck. Use it on internet links only.- Unescaped spaces in remote paths. Quote the remote path; rsync 3.2.4+ handles it without extra backslashes, older versions needed
-s(--protect-args). - rsync is not a backup by itself. A mirror copies your mistakes too. Keep dated copies with
--link-destor use snapshots (Timeshift and Snapper).
Every option is documented in the rsync manual.
Frequently asked questions
What is the difference between rsync src and src/?
Without the trailing slash rsync copies the directory itself, so rsync -a src dest/ creates dest/src/. With it, rsync -a src/ dest/ copies only the contents of src into dest.
How do I see what rsync will do before running it?
Add -n (--dry-run) together with -v or -i. Nothing is transferred or deleted, but rsync lists every change it would make.
Does rsync delete files on the destination?
Not by default. Only --delete (and its variants) removes files from the destination that no longer exist in the source. Always test it with -n first.
How do I use rsync with a different SSH port or key?
Pass the SSH command with -e: rsync -a -e 'ssh -p 2222 -i ~/.ssh/backup_key' src/ user@host:/backup/.
Can rsync resume an interrupted transfer?
Yes. Rerun the same command; rsync skips files that are already complete. Add --partial (or -P) so half-transferred large files are kept and continued instead of restarted.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.