# rsync — Efficient File Sync and Backup

> Practical guide to rsync — transfers only the differences between source and destination: ideal for backups, mirroring and remote file sync over SSH.

Source: https://www.jpkc.com/db/en/cheatsheets/backup-sync/rsync/

<!-- PROSE:intro -->
rsync is the go-to tool for copying and synchronizing files and entire directory trees quickly – both locally and over SSH. Its clever delta algorithm transfers only the parts that have changed since the last run instead of resending everything every time. That makes it the first choice for backups, website deployments, directory mirroring and incremental snapshots. This guide walks you through the options you reach for daily – from archive mode through filter rules to the mirroring `--delete`.
<!-- PROSE:intro:end -->

## Basic Usage

`rsync <source> <destination>` — Copy a file from source to destination locally.

```bash
rsync file.txt /backup/file.txt
```

`rsync -r <source_dir> <destination_dir>` — Copy a directory recursively. Note: trailing slash on source matters.

```bash
rsync -r ./project/ /backup/project/
```

`rsync -a <source> <destination>` — Archive mode. Preserves permissions, timestamps, symlinks, owner, and group. Most commonly used flag.

```bash
rsync -a ./project/ /backup/project/
```

`rsync -av <source> <destination>` — Archive mode with verbose output. Shows each file being transferred.

```bash
rsync -av ./project/ /backup/project/
```

`rsync -avh <source> <destination>` — Archive mode with verbose output and human-readable file sizes.

```bash
rsync -avh ./photos/ /backup/photos/
```

## Trailing Slash Behavior

`rsync -a <source_dir>/ <destination_dir>/` — Trailing slash on source: copy the contents of source_dir into destination_dir.

```bash
rsync -a ./project/ /backup/project/
```

`rsync -a <source_dir> <destination_dir>/` — No trailing slash on source: copy source_dir itself into destination_dir (creates destination_dir/source_dir/).

```bash
rsync -a ./project /backup/
```

## Remote Transfers (SSH)

`rsync -avz <source> <user>@<host>:<destination>` — Copy local files to a remote server via SSH with compression.

```bash
rsync -avz ./dist/ deploy@server.com:/var/www/html/
```

`rsync -avz <user>@<host>:<source> <destination>` — Copy files from a remote server to the local machine.

```bash
rsync -avz deploy@server.com:/var/www/html/ ./backup/
```

`rsync -avz -e "ssh -p <port>" <source> <user>@<host>:<destination>` — Use a custom SSH port for the transfer.

```bash
rsync -avz -e "ssh -p 2222" ./files/ user@server.com:/data/
```

`rsync -avz -e "ssh -i <keyfile>" <source> <user>@<host>:<destination>` — Use a specific SSH private key for authentication.

```bash
rsync -avz -e "ssh -i ~/.ssh/deploy_key" ./dist/ deploy@server.com:/var/www/
```

`rsync -avz <user>@<host1>:<source> <user>@<host2>:<destination>` — Sync files between two remote servers (data flows through local machine).

```bash
rsync -avz user@server1.com:/data/ user@server2.com:/backup/
```

## Dry Run & Progress

`rsync -avn <source> <destination>` — Dry run. Show what would be transferred without actually doing it.

```bash
rsync -avn ./project/ /backup/project/
```

`rsync -av --progress <source> <destination>` — Show per-file transfer progress with speed and remaining time.

```bash
rsync -av --progress ./large-files/ /backup/large-files/
```

`rsync -av --stats <source> <destination>` — Show a summary of transfer statistics at the end.

```bash
rsync -av --stats ./project/ /backup/project/
```

`rsync -av --info=progress2 <source> <destination>` — Show overall transfer progress instead of per-file progress.

```bash
rsync -av --info=progress2 ./photos/ /backup/photos/
```

## Delete & Sync

`rsync -av --delete <source> <destination>` — Delete files in destination that no longer exist in source, making destination an exact mirror. Destructive: always do a dry run with `-n`/`--dry-run` first.

```bash
rsync -av --delete ./website/ /var/www/html/
```

`rsync -av --delete-after <source> <destination>` — Delete extraneous files after the transfer completes (safer than default).

```bash
rsync -av --delete-after ./website/ /var/www/html/
```

`rsync -av --delete-excluded <source> <destination>` — Also delete excluded files from the destination.

```bash
rsync -av --delete-excluded --exclude='*.tmp' ./project/ /backup/
```

`rsync -av --force --delete <source> <destination>` — Force deletion of non-empty directories in destination.

```bash
rsync -av --force --delete ./project/ /backup/project/
```

## Exclude & Include Filters

`rsync -av --exclude='<pattern>' <source> <destination>` — Exclude files matching a pattern from the transfer.

```bash
rsync -av --exclude='node_modules' ./project/ /backup/project/
```

`rsync -av --exclude='*.log' --exclude='*.tmp' <source> <destination>` — Exclude multiple patterns by repeating the flag.

```bash
rsync -av --exclude='*.log' --exclude='*.tmp' ./app/ /backup/app/
```

`rsync -av --exclude-from='<file>' <source> <destination>` — Read exclude patterns from a file (one pattern per line).

```bash
rsync -av --exclude-from='.rsyncignore' ./project/ /backup/project/
```

`rsync -av --include='<pattern>' --exclude='*' <source> <destination>` — Include only files matching a pattern, exclude everything else.

```bash
rsync -av --include='*.jpg' --exclude='*' ./photos/ /backup/photos/
```

`rsync -av --filter='- <pattern>' <source> <destination>` — Use filter rules for fine-grained control. Prefix '-' excludes, '+' includes.

```bash
rsync -av --filter='- *.log' --filter='- /tmp/' ./app/ /backup/app/
```

`rsync -av --include='*/' --include='*.php' --exclude='*' <source> <destination>` — Sync only specific file types while keeping directory structure.

```bash
rsync -av --include='*/' --include='*.php' --exclude='*' ./src/ /backup/src/
```

## Compression & Bandwidth

`rsync -avz <source> <destination>` — Compress data during transfer. Useful for remote transfers over slow connections.

```bash
rsync -avz ./project/ user@server.com:/backup/
```

`rsync -avz --compress-level=<level> <source> <destination>` — Set compression level (0-9). Higher means better compression but slower.

```bash
rsync -avz --compress-level=9 ./data/ user@server.com:/backup/
```

`rsync -av --bwlimit=<kbps> <source> <destination>` — Limit transfer bandwidth in kilobytes per second.

```bash
rsync -av --bwlimit=5000 ./large-files/ user@server.com:/backup/
```

## Permissions & Ownership

`rsync -av --chmod=<permissions> <source> <destination>` — Set specific permissions on the destination files.

```bash
rsync -av --chmod=D755,F644 ./website/ /var/www/html/
```

`rsync -av --chown=<user>:<group> <source> <destination>` — Set owner and group on the destination files (requires root).

```bash
rsync -av --chown=www-data:www-data ./website/ /var/www/html/
```

`rsync -av --no-perms <source> <destination>` — Do not preserve file permissions.

```bash
rsync -av --no-perms ./files/ /shared/files/
```

`rsync -av --no-owner --no-group <source> <destination>` — Do not preserve owner and group information.

```bash
rsync -av --no-owner --no-group ./files/ /backup/files/
```

## Partial Transfers & Resume

`rsync -avP <source> <destination>` — Show progress and keep partial files. Equivalent to --partial --progress. Allows resuming interrupted transfers.

```bash
rsync -avP ./large-file.iso user@server.com:/data/
```

`rsync -av --partial <source> <destination>` — Keep partially transferred files so they can be resumed later.

```bash
rsync -av --partial ./backup.tar.gz user@server.com:/backup/
```

`rsync -av --partial-dir=<dir> <source> <destination>` — Store partial files in a separate directory instead of in-place.

```bash
rsync -av --partial-dir=.rsync-partial ./data/ user@server.com:/data/
```

`rsync -av --append-verify <source> <destination>` — Resume transfer by appending to partial files and verify with checksum.

```bash
rsync -av --append-verify ./large-file.tar user@server.com:/data/
```

## Checksum & Verification

`rsync -avc <source> <destination>` — Use checksum instead of modification time and size to decide which files to transfer.

```bash
rsync -avc ./important-data/ /backup/important-data/
```

`rsync -av --checksum <source> <destination>` — Skip files based on checksum, not modification time. Slower but more accurate.

```bash
rsync -av --checksum ./data/ /mirror/data/
```

`rsync -av --ignore-existing <source> <destination>` — Skip files that already exist on the destination.

```bash
rsync -av --ignore-existing ./new-files/ /archive/
```

`rsync -av --update <source> <destination>` — Skip files that are newer on the destination.

```bash
rsync -av --update ./project/ /shared/project/
```

## Backup & Versioning

`rsync -av --backup --suffix='.<date>' <source> <destination>` — Create backup copies of overwritten files with a custom suffix.

```bash
rsync -av --backup --suffix='.bak' ./config/ /etc/app/
```

`rsync -av --backup --backup-dir=<dir> <source> <destination>` — Move overwritten or deleted files to a separate backup directory.

```bash
rsync -av --backup --backup-dir=/backup/old/ ./website/ /var/www/html/
```

`rsync -av --link-dest=<dir> <source> <destination>` — Hard-link unchanged files to a previous backup. Creates space-efficient incremental backups.

```bash
rsync -av --link-dest=/backup/2024-01-01/ ./data/ /backup/2024-01-02/
```

## Common Recipes

`rsync -avz --delete <source>/ <user>@<host>:<destination>/` — Deploy a website: mirror local directory to remote server, remove stale files. With `--delete`, dry-run first.

```bash
rsync -avz --delete ./dist/ deploy@server.com:/var/www/html/
```

`rsync -avz --exclude='.git' --exclude='node_modules' <source>/ <destination>/` — Sync a project while excluding version control and dependency directories.

```bash
rsync -avz --exclude='.git' --exclude='node_modules' ./project/ /backup/project/
```

`rsync -av --delete --link-dest=<prev_backup> <source>/ <new_backup>/` — Create an incremental backup using hard links to the previous backup.

```bash
rsync -av --delete --link-dest=/backup/daily.1/ /home/user/ /backup/daily.0/
```

`rsync -avz --progress -e ssh <source>/ <user>@<host>:<destination>/` — Full remote sync with compression, progress display, and SSH.

```bash
rsync -avz --progress -e ssh ./photos/ user@nas.local:/volume1/photos/
```

`rsync -av --dry-run --delete <source>/ <destination>/` — Preview a sync with deletions. Always dry-run first before using --delete.

```bash
rsync -av --dry-run --delete ./website/ /var/www/html/
```

<!-- PROSE:outro -->
## Conclusion

rsync is robust, available everywhere and, thanks to its delta transfer, unbeatably efficient – a tool that suits simple copies just as well as sophisticated incremental backup strategies with `--link-dest`. Its biggest hazard is `--delete`: a misplaced trailing slash or swapped source/destination argument can wipe the wrong data. Make it a habit to preview every mirroring sync with `-n`/`--dry-run`, and pay close attention to the trailing-slash semantics of your paths.

## Further Reading

- [rsync – official project site](https://rsync.samba.org/) – downloads, man page and documentation
- [rsync – Wikipedia](https://en.wikipedia.org/wiki/Rsync) – background, mechanics and history of the delta algorithm
<!-- PROSE:outro:end -->

## Related Commands

- [borgbackup](https://www.jpkc.com/db/en/cheatsheets/backup-sync/borgbackup/) – deduplicating, compressed and encrypted backups
- [duplicity](https://www.jpkc.com/db/en/cheatsheets/backup-sync/duplicity/) – encrypted incremental backups to many storage backends
- [rclone](https://www.jpkc.com/db/en/cheatsheets/backup-sync/rclone/) – sync with cloud storage such as S3, Google Drive and more

