Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

rsync Options Worth Knowing: A Practical Read of the Man Page

Sean

Platform Writer

Aug 10, 2026
8 min read

The rsync man page is one of the longest in a standard Linux install, and about fifteen options cover almost every real use. The one thing to internalise before any of them is the trailing slash on the source path, because it changes where your files land and the man page mentions it almost in passing.

rsync Options Worth Knowing: A Practical Read of the Man Page

rsync transfers only what differs, preserves metadata, works locally or over SSH, and can delete files removed at the source. That combination makes it the right tool for backups, deployments, and migrations — and the deletion capability makes a typo genuinely expensive.

Table of contents

The trailing slash rule

This is the single most common rsync mistake and it takes one line to explain.

# WITH trailing slash: copy the CONTENTS of src into dest
rsync -a /src/ /dest/
# -> /dest/file1, /dest/file2

# WITHOUT trailing slash: copy the DIRECTORY src into dest
rsync -a /src /dest/
# -> /dest/src/file1, /dest/src/file2

The trailing slash on the source means the contents of. On the destination it makes no difference.

Getting this wrong produces /var/www/html/html/index.html and a confusing five minutes. Getting it wrong alongside --delete produces something worse.

The habit that prevents all of it: run with -n first, read the output, then run for real.

The flags that cover most usage

rsync -avz --progress /src/ user@host:/dest/
  • -a (archive) — the workhorse. Equivalent to -rlptgoD: recursive, preserve symlinks, permissions, times, group, owner, and device files. Almost every rsync command starts here.
  • -v (verbose) — list files as they transfer. -vv for more than you want.
  • -z (compress) — compress in transit. Useful over a network, pointless locally, and counterproductive on already-compressed data.
  • --progress — per-file progress. --info=progress2 gives one overall bar instead, which is usually what you actually wanted.
  • -n / --dry-run — show what would happen and change nothing. Use it every time.
  • -h — human-readable sizes.
  • -P — shorthand for --partial --progress, keeping partial transfers so an interrupted large file resumes.

-a does not imply -z or -H. Hardlinks specifically need -H, and without it a tree with many hardlinks expands dramatically on the destination — a classic surprise when copying a backup directory.

—delete, and how to use it without regret

By default rsync only adds and updates. --delete removes files from the destination that no longer exist at the source, which is what makes it a sync rather than a copy.

# Make dest an exact mirror of src
rsync -av --delete /src/ /dest/

# ALWAYS do this first
rsync -avn --delete /src/ /dest/ | head -50

# Refuse to run if more than 10% of files would be deleted
rsync -av --delete --max-delete=100 /src/ /dest/

--max-delete is the seatbelt. If a mount failed and your source directory is empty, --delete will happily empty the destination to match. --max-delete makes rsync abort instead.

The related variants matter for correctness:

  • --delete-before — delete first. Necessary when the destination is short on space.
  • --delete-during — default in modern versions; deletes as it goes.
  • --delete-after — delete last. Safest when the transfer might be interrupted, since files are not removed until the new ones are in place.
  • --delete-excluded — also delete files matching your exclude patterns. Rarely what you want, and it surprises people.

For anything unattended, --delete-after with --max-delete is the combination that fails safely.

Excludes, and getting the patterns right

rsync -av \
  --exclude='.git/' \
  --exclude='node_modules/' \
  --exclude='*.log' \
  --exclude='.env' \
  /src/ /dest/

# Patterns from a file, which scales better
rsync -av --exclude-from=.rsyncignore /src/ /dest/

# Exclude everything except what you name -- order matters
rsync -av --include='*/' --include='*.jpg' --exclude='*' /src/ /dest/

Pattern rules worth knowing: a leading / anchors to the transfer root, a trailing / matches directories only, and ** crosses directory boundaries while * does not.

Rules are evaluated in order and the first match wins. That is why the include-only example needs --include='*/' first — without it, rsync never descends into subdirectories to find the files you wanted.

Excluding .env and similar is worth making a habit rather than a decision. Syncing a development tree to a server has copied credentials into public web roots more than once.

Over SSH, and in scripts

# Non-standard port and a specific key
rsync -avz -e 'ssh -p 2222 -i ~/.ssh/deploy_key' /src/ user@host:/dest/

# Bandwidth cap, so you do not saturate the link
rsync -avz --bwlimit=5000 /src/ user@host:/dest/    # KB/s

# Resume-friendly for large files over a flaky link
rsync -avzP --timeout=300 /src/ user@host:/dest/

# Preserve hardlinks and ACLs on a real backup
rsync -aHAX --numeric-ids /src/ user@host:/dest/

--numeric-ids matters when the two machines have different user databases. Without it, rsync maps by name and files can land owned by whichever local user happens to hold that name.

For scripts, check the exit code and know that 24 is usually benign:

rsync -a --delete /src/ /dest/
status=$?

case $status in
  0)  echo 'ok' ;;
  24) echo 'ok -- some source files vanished during transfer' ;;
  23) echo 'partial transfer: permission or missing file errors' >&2; exit 1 ;;
  *)  echo "rsync failed: $status" >&2; exit 1 ;;
esac

Exit 24 means files disappeared while rsync was reading them — normal on a live system with logs and temp files, and not worth alerting on.

The most useful rsync feature that most people never encounter. --link-dest hardlinks unchanged files to a previous backup instead of copying them, so each snapshot appears complete while only new and changed files consume space.

#!/usr/bin/env bash
set -euo pipefail

SRC=/var/www/
DEST=/backups
TODAY=$(date +%F)

rsync -aH --delete \
  --link-dest="$DEST/latest" \
  "$SRC" "$DEST/$TODAY/"

ln -sfn "$DEST/$TODAY" "$DEST/latest"

# Keep 30 days
find "$DEST" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +

Thirty daily snapshots of a 50GB tree that changes slowly might occupy 55GB total, and each directory can be browsed and restored from directly with cp. No proprietary format, no restore tool.

This is not a substitute for backups you cannot reach from the machine being backed up. A snapshot directory on the same host protects against deletion and not against the host failing. For databases specifically, filesystem-level copies of a running database are not consistent — use the database’s own dump or snapshot mechanism, which for managed Postgres and MySQL on RunxBuild is handled by scheduled backups rather than by rsync.

How this fits the rest of the stack

Learn -avz, respect the trailing slash, and run -n before anything with --delete. Add --max-delete for unattended jobs and --link-dest when you want cheap snapshots you can browse. And do not rsync a live database directory. If you are pricing a setup where backups are handled at the database rather than the filesystem, the RunxBuild hosting calculator shows the database as its own line item.

Useful related references:

FAQ

What does the trailing slash do in rsync?

On the source path it means the contents of that directory rather than the directory itself. rsync -a /src/ /dest/ puts files directly in /dest, while rsync -a /src /dest/ creates /dest/src. On the destination it makes no difference.

What does the -a flag include?

Archive mode is equivalent to -rlptgoD: recursive, preserve symlinks, permissions, modification times, group, owner, and device files. It does not include compression, hardlink preservation, or ACLs — those need -z, -H, and -A.

How do I avoid deleting the wrong files with —delete?

Run the same command with -n first and read the output. Add —max-delete so rsync aborts rather than removing an unexpected number of files, which protects you when a failed mount makes the source look empty.

What does rsync exit code 24 mean?

Some source files vanished while the transfer was running. On a live system with log rotation and temp files this is normal and usually safe to treat as success.

Can I use rsync to back up a database?

Not a running one. Filesystem copies of live database files are inconsistent because writes happen during the transfer. Use the database’s own dump or snapshot mechanism, then rsync the resulting file if you need to move it.

#man rsync#rsync options#file synchronization#backup#rsync delete