rsync without losing data

general / published / guide #33 / ≈ 3 min read

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 --delete with 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 -r instead of rsync for a huge transfer — works, but you can't resume if interrupted. Use rsync next time.

← back to index