When you need to copy large directory trees, synchronise remote backups, or mirror content between servers, rsync is the tool of choice on Red Hat Enterprise Linux 8. Unlike a plain cp or scp, rsync transmits only the differences between source and destination, making subsequent runs dramatically faster. Its rich option set covers everything from simple local copies to efficient incremental backups over SSH. This guide covers the flags and workflows you will reach for most often.
Prerequisites
- A running RHEL 8 system with root or sudo access
rsyncinstalled — it is available in the default AppStream repository (sudo dnf install -y rsync)- SSH access to a remote host for remote-sync steps
- Basic understanding of Linux file paths and permissions
Step 1 — Basic Local Sync with -avz –progress
The most common combination of flags is -avz: archive mode (preserves permissions, timestamps, symlinks, and ownership), verbose output, and compression during transfer. Adding --progress shows per-file transfer speed and a running total.
# Sync /data/source/ into /backup/dest/ (trailing slash on source is important)
rsync -avz --progress /data/source/ /backup/dest/
# Without trailing slash: copies the source directory itself into dest
rsync -avz --progress /data/source /backup/dest/
# Dry run — show what would be transferred without making any changes
rsync -avz --dry-run /data/source/ /backup/dest/
A trailing slash on the source path means “copy the contents of this directory.” Without it, rsync copies the directory itself as a subdirectory of the destination. This is one of the most common sources of confusion — always use --dry-run first when you are unsure.
Step 2 — Delete and Filter with –delete, –exclude, –include
The --delete flag removes files from the destination that no longer exist in the source, keeping the two directories in exact sync. Use --exclude to skip specific patterns and --include to override an exclusion rule.
# Mirror source exactly — delete files on dest that are gone from source
rsync -avz --delete /data/source/ /backup/dest/
# Exclude all log files and a specific subdirectory
rsync -avz --exclude '*.log' --exclude 'tmp/' /data/source/ /backup/dest/
# Exclude everything except .conf files (order matters: include before exclude)
rsync -avz --include '*.conf' --exclude '*' /data/source/ /backup/dest/
# Use an external filter file for complex rules
rsync -avz --exclude-from=/etc/rsync-excludes.txt /data/source/ /backup/dest/
Step 3 — Remote Sync Over SSH
By default rsync uses SSH for remote transfers. Use -e ssh to pass options to the SSH client, such as a non-standard port or a specific identity file.
# Push local directory to remote server (standard SSH port)
rsync -avz /data/source/ user@remote-host:/backup/dest/
# Pull from remote to local
rsync -avz user@remote-host:/data/source/ /backup/dest/
# Use a non-standard SSH port and specific key
rsync -avz -e "ssh -p 2222 -i ~/.ssh/backup_key"
/data/source/ user@remote-host:/backup/dest/
# Limit bandwidth to 5 MB/s to avoid saturating a link
rsync -avz --bwlimit=5000 /data/source/ user@remote-host:/backup/dest/
Step 4 — Efficient Comparisons with –checksum and –ignore-existing
By default rsync compares files by size and modification time — fast but not foolproof. --checksum forces an MD5/SHA1 comparison which is slower but accurate. Conversely, --ignore-existing skips files already present on the destination regardless of content.
# Force checksum comparison (accurate but CPU-intensive)
rsync -avz --checksum /data/source/ /backup/dest/
# Skip files that already exist on the destination (one-way seed)
rsync -avz --ignore-existing /data/source/ /backup/dest/
# Only update files if the source is newer than the destination
rsync -avz --update /data/source/ /backup/dest/
Step 5 — Incremental Backups with –link-dest
The --link-dest option enables time-stamped incremental backups by hard-linking unchanged files to a previous snapshot instead of copying them. Each backup directory appears complete on disk but only the changed files consume additional space.
# Create a date-stamped backup directory
BACKUP_DATE=$(date +%Y-%m-%d)
LATEST=/backup/snapshots/latest
# Run incremental backup against the previous snapshot
rsync -avz --delete
--link-dest="$LATEST"
/data/source/
"/backup/snapshots/$BACKUP_DATE/"
# Update the 'latest' symlink to point at the newest snapshot
ln -sfn "/backup/snapshots/$BACKUP_DATE" "$LATEST"
# List all snapshots
ls -lh /backup/snapshots/
Conclusion
You have seen how rsync handles everything from a simple local copy to bandwidth-limited remote transfers and space-efficient incremental snapshots using hard links. The combination of --dry-run before every production sync, --delete for true mirroring, and --link-dest for incremental backups covers the vast majority of real-world backup and synchronisation requirements on RHEL 8. Always test new rsync commands with --dry-run until you are confident in the source/destination layout and filter rules.
Next steps: How to Schedule Automated Tasks with cron and anacron on RHEL 8, How to Configure an rsync Daemon on RHEL 8, and How to Use tar for Archiving and Compression on RHEL 8.