rsync is the standard file synchronization tool on Linux and Unix systems. It transfers only the differences between source and destination files (delta-transfer algorithm), making it faster than copying everything with cp or scp. This guide covers rsync syntax, common flags, local and remote sync, exclude patterns, mirroring, dry runs, bandwidth limiting, and scheduled backups with cron.
Install rsync
rsync is pre-installed on most Linux distributions. If missing, install it:
# RHEL 10/9, Rocky Linux, AlmaLinux, Fedora
sudo dnf -y install rsync
# Debian, Ubuntu
sudo apt update && sudo apt -y install rsync
# Arch Linux, Manjaro
sudo pacman -S rsync
# FreeBSD
sudo pkg install rsync
Verify the installed version:
$ rsync --version | head -1
rsync version 3.3.0 protocol version 32
Basic Syntax
# Local sync
rsync [OPTIONS] SOURCE DESTINATION
# Push to remote
rsync [OPTIONS] SOURCE USER@HOST:DESTINATION
# Pull from remote
rsync [OPTIONS] USER@HOST:SOURCE DESTINATION
Common rsync Options
| Flag | Description |
|---|---|
-a | Archive mode – preserves permissions, ownership, timestamps, symlinks, recursion (equals -rlptgoD) |
-v | Verbose output |
-z | Compress data during transfer |
-h | Human-readable file sizes |
-P | Show progress + keep partial files (equals --progress --partial) |
--progress | Show per-file transfer progress |
--info=progress2 | Show overall transfer progress (percentage of total) |
-n, --dry-run | Simulate the transfer without making changes |
--delete | Delete files in destination that don’t exist in source |
-e | Specify remote shell (e.g., -e 'ssh -p 2222') |
--exclude | Exclude files matching a pattern |
--include | Include files matching a pattern |
--bwlimit | Limit bandwidth in KB/s |
--backup | Make backups of overwritten files |
--max-size | Skip files larger than given size |
--min-size | Skip files smaller than given size |
-W | Copy whole files (skip delta algorithm) |
-q | Quiet mode – suppress non-error messages |
The most common combination is rsync -avhP which gives you archive mode, verbose output, human-readable sizes, and progress display.
The Trailing Slash Rule
The trailing slash on the source path changes rsync behavior significantly. This is one of the most common sources of confusion:
# WITH trailing slash: copies CONTENTS of mydir into /backup/
rsync -avh /home/admin/mydir/ /backup/
# Result: /backup/file1.txt, /backup/file2.txt
# WITHOUT trailing slash: copies the DIRECTORY itself into /backup/
rsync -avh /home/admin/mydir /backup/
# Result: /backup/mydir/file1.txt, /backup/mydir/file2.txt
The destination path is not affected by trailing slashes – only the source matters.
Local Sync Examples
Copy a single file to another directory:
rsync -avh backup.tar.gz /tmp/
Sync the contents of one directory to another with progress:
rsync -avhP /home/admin/project/ /mnt/backup/project/
Show overall transfer progress instead of per-file:
rsync -avh --info=progress2 /home/admin/project/ /mnt/backup/project/
Remote Sync over SSH
rsync uses SSH as its default transport. Push local files to a remote server:
rsync -avhP /home/admin/project/ [email protected]:/backup/project/
Pull files from a remote server to local:
rsync -avhP [email protected]:/var/log/nginx/ /tmp/nginx-logs/
Rsync with Custom SSH Port
If the remote server runs SSH on a non-standard port, use the -e flag. For example, if SSH is on port 2222 (see our guide on changing the SSH port):
rsync -avhP -e 'ssh -p 2222' /home/admin/project/ [email protected]:/backup/project/
Rsync with a Specific SSH Key
rsync -avhP -e 'ssh -i ~/.ssh/backup_key' /data/ [email protected]:/backup/data/
Dry Run – Test Before Syncing
Always test with --dry-run (or -n) before running destructive operations like --delete. This shows what would happen without making any changes:
rsync -avhn --delete /home/admin/project/ [email protected]:/backup/project/
Review the output carefully. Lines prefixed with deleting show files that would be removed from the destination.
Mirror with –delete
The --delete flag makes the destination an exact mirror of the source. Files that exist in the destination but not in the source are removed:
rsync -avhP --delete /home/admin/website/ [email protected]:/var/www/website/
This is the standard approach for deploying websites and keeping backup mirrors in sync. Always do a --dry-run first to avoid accidental data loss.
Exclude and Include Patterns
Skip specific files or directories during transfer:
# Exclude a single directory
rsync -avhP --exclude='node_modules' /home/admin/project/ /backup/project/
# Exclude multiple patterns
rsync -avhP --exclude='*.log' --exclude='*.tmp' --exclude='.git' /home/admin/project/ /backup/project/
# Include only specific files, exclude the rest
rsync -avhP --include='*.conf' --exclude='*' /etc/ /backup/configs/
For complex exclude rules, use a file:
vi exclude-list.txt
Add one pattern per line:
node_modules/
*.log
*.tmp
.git/
__pycache__/
.env
Then reference the file:
rsync -avhP --exclude-from='exclude-list.txt' /home/admin/project/ /backup/project/
Limit Transfer by File Size
Skip files that are larger or smaller than a threshold:
# Skip files larger than 100MB
rsync -avhP --max-size='100m' /data/ [email protected]:/backup/data/
# Skip files smaller than 10KB
rsync -avhP --min-size='10k' /data/ [email protected]:/backup/data/
Bandwidth Limiting
Prevent rsync from saturating the network link during production hours:
# Limit to 5 MB/s
rsync -avhP --bwlimit=5000 /data/ [email protected]:/backup/data/
# Limit to 1 MB/s
rsync -avhP --bwlimit=1000 /data/ [email protected]:/backup/data/
The value is in KB/s. Use 5000 for 5 MB/s, 10000 for 10 MB/s.
Resume Partial Transfers
If a large transfer gets interrupted, the -P flag (which equals --partial --progress) keeps partially transferred files and resumes from where it stopped:
rsync -avhP /data/large-backup.tar.gz [email protected]:/backup/
Without --partial, rsync deletes incomplete files and starts over on the next run.
Backup with Versioning
The --backup flag keeps a copy of overwritten files instead of replacing them. Combined with --backup-dir, it creates a versioned backup structure:
rsync -avhP --delete --backup --backup-dir=/backup/incremental/$(date +%F) \
/home/admin/project/ /backup/current/project/
This keeps /backup/current/ as an exact mirror while saving overwritten files in dated subdirectories under /backup/incremental/.
Scheduled Backups with Cron
Automate rsync by adding it to cron. Open the crontab editor:
crontab -e
Add a job to run daily at 2 AM:
# Daily backup at 2 AM
0 2 * * * rsync -avh --delete /home/admin/project/ [email protected]:/backup/project/ >> /var/log/rsync-backup.log 2>&1
For more sophisticated backup automation, see our guide on bash scripts for automating Linux backups. For real-time sync, check rsync with lsyncd for live file synchronization.
Quick Reference
| Task | Command |
|---|---|
| Local copy with progress | rsync -avhP src/ dest/ |
| Push to remote | rsync -avhP src/ user@host:dest/ |
| Pull from remote | rsync -avhP user@host:src/ dest/ |
| Mirror (exact copy) | rsync -avhP --delete src/ dest/ |
| Dry run | rsync -avhn --delete src/ dest/ |
| Custom SSH port | rsync -avhP -e 'ssh -p 2222' src/ user@host:dest/ |
| Exclude patterns | rsync -avhP --exclude='*.log' src/ dest/ |
| Limit bandwidth | rsync -avhP --bwlimit=5000 src/ dest/ |
| Resume partial | rsync -avhP src/ dest/ (the -P enables resume) |
Conclusion
rsync is the go-to tool for file synchronization, backups, and deployments on Linux. The delta-transfer algorithm means only changed bytes are sent over the network, making it far more efficient than scp for recurring transfers. For production use, always test with --dry-run before using --delete, and consider combining rsync with cron for automated nightly backups.
Related guides:
- Use Rsync + Lsyncd For File Synchronization on Linux
- Using SCP on Linux to Securely Transfer Files
- Bash Script To Automate Linux Directories Backups
- SSH Commands Cheat Sheet for Linux SysAdmins
- 10 Best Free Linux Backup Tools




































































