rsync copies files. That's the whole job. What makes it special is how: it only sends the differences, it preserves permissions, it works over SSH, it can resume interrupted transfers. It's the default tool for "copy a folder somewhere else" and the default tool for "do a backup."
This guide is the careful walkthrough — with extra attention to the one thing that bites everyone the first time (the trailing slash).
The form of every rsync command
rsync [flags] source destination
That's it. source and destination can be local paths or user@host:/path for remote.
The starter flag combo: -av
rsync -av /home/me/photos/ /backup/photos/
The flags:
-a— "archive mode." A bundle of useful defaults: recursive, preserve permissions, preserve timestamps, preserve symlinks, preserve owner and group. This is what you want 99% of the time.-v— verbose: print what's being copied.
That single command copies photos/ from your home directory to /backup/photos/, preserving everything that matters.
The trailing-slash trick (READ THIS)
The single most common rsync mistake. Look at these two commands:
rsync -av /home/me/photos /backup/ # copies the folder itself
rsync -av /home/me/photos/ /backup/ # copies the CONTENTS of the folder
The first makes /backup/photos/. The second makes /backup/cat.jpg, /backup/dog.jpg, … directly in /backup/.
The trailing slash on the destination doesn't matter. The trailing slash on the source changes everything. When in doubt: include it, and put the full target name on the destination side.
The safety habit: --dry-run
Before any rsync that could overwrite something:
rsync -avn /home/me/photos/ /backup/photos/
-n means "don't actually copy, just show me what you would do." Read the list. If it looks right, run the same command without the -n.
This habit has saved more sysadmins than any other single trick.
Copy over SSH
If either source or destination is on another machine, rsync uses SSH automatically:
rsync -av /home/me/photos/ you@server:/backup/photos/ # push (upload)
rsync -av you@server:/var/log/ /tmp/server-logs/ # pull (download)
You can pass SSH options too:
rsync -av -e "ssh -p 2222" /home/me/photos/ you@server:/backup/photos/
--delete: the "make destination match source exactly" flag
By default, rsync only adds and updates files. It never removes. To make the destination a true mirror — deleting files that no longer exist in the source — add --delete:
rsync -av --delete /home/me/photos/ /backup/photos/
Always dry-run this one first. The day you point this at the wrong source is the day it cleanly empties your destination.
Resume an interrupted transfer
rsync -avP /huge.iso you@server:/backups/
-P is two things bundled: --partial (keep partly-transferred files around) and --progress (show a percent meter). If the connection drops mid-file, re-run the same command — rsync picks up where it stopped.
Skip files: --exclude
rsync -av --exclude='node_modules' --exclude='.git' src/ /backup/src/
Each --exclude pattern is matched against file/dir names. Glob characters work (*.tmp).
For long exclude lists, put them in a file:
rsync -av --exclude-from=ignore.txt src/ /backup/src/
A useful pattern: nightly backup of your home
rsync -av --delete
--exclude='.cache' --exclude='Downloads' --exclude='node_modules'
/home/me/ /mnt/usb-backup/me/
Put this in a cron job (see the cron + systemd timers guide) and you have a working backup.
Common mistakes, summarised
- Lost a trailing slash — files ended up nested one level too deep. Fix the source, re-run.
- Used
--deletewith the wrong source — the destination got emptied. Restore from a backup; learn the lesson. - Forgot
-a— permissions, times, or symlinks weren't preserved. Re-run with-a. - Used
cp -rinstead of rsync for a huge transfer — works, but you can't resume if interrupted. Use rsync next time.