Skip to main content
Blog|
How-to guides

How to Sync Directories with rsync

|
Mar 18, 2026|7 min read
HOW-TO GUIDESHow to Sync Directories withrsyncHOSTNEYhostney.comMarch 18, 2026

rsync synchronizes the contents of one directory with another. It compares both sides and transfers only the files that have changed. If you sync a directory today and sync it again tomorrow after editing two files, rsync transfers only those two files. Everything else is skipped.

This makes rsync the standard tool for keeping directories in sync, whether they are on the same machine or on different servers connected over SSH. This guide covers every common directory sync scenario with practical examples you can copy and adapt.

For a full reference of every rsync flag and what it does, see the rsync commands reference guide.

Installing rsync#

rsync is pre-installed on most Linux distributions and macOS. Check with:

rsync --version

If it is not installed, the installation depends on your distribution.

Install rsync on Ubuntu/Debian

sudo apt update && sudo apt install rsync

Install rsync on CentOS/RHEL

sudo dnf install rsync

Install rsync on macOS

Included by default. For a newer version via Homebrew:

brew install rsync

rsync on Windows

rsync is not natively available on Windows. The practical options are:

  • WSL (Windows Subsystem for Linux): install a Linux distribution through WSL and use rsync normally inside it
  • Cygwin: includes rsync in its package repository
  • cwRsync: a standalone Windows port of rsync

For simple one-off file transfers on Windows without rsync, SCP is built into Windows 10 and 11 via OpenSSH and requires no additional installation.

How rsync handles directories#

Before running any sync, understand two things about how rsync treats directory paths. Getting these wrong is the most common source of unexpected results.

Trailing slash on the source

A trailing slash on the source path means “the contents of this directory.” No trailing slash means “this directory and its contents.”

With trailing slash – copies contents into destination:

rsync -av /home/user/project/ /backup/project/

The files inside project/ go directly into /backup/project/ .

Without trailing slash – copies the directory itself:

rsync -av /home/user/project /backup/

This creates /backup/project/ and puts the files inside it.

If you are unsure, run with --dry-run first to see what rsync would do without actually transferring anything:

rsync -avn /home/user/project/ /backup/project/

Archive mode (-a)

You will see -a on nearly every rsync command in this guide. It is a shorthand for recursive copy with metadata preservation: permissions, timestamps, ownership, symlinks. Without -a , rsync does not recurse into subdirectories and does not preserve file attributes. See the rsync commands reference for the full breakdown of what -a includes.

Syncing directories on the same machine#

Sync one directory to another

rsync -av /home/user/project/ /backup/project/

Copies everything in /home/user/project/ to /backup/project/ . On the first run, all files are transferred. On subsequent runs, only changed files are transferred.

Mirror a directory (delete extras at destination)

By default, rsync only adds and updates files. It never deletes anything at the destination. If you delete a file from the source, it remains in the destination after the next sync.

To make the destination an exact mirror of the source, add --delete :

rsync -av --delete /home/user/project/ /backup/project/

Files that exist in /backup/project/ but not in /home/user/project/ are deleted. Always preview with --dry-run before using --delete :

rsync -avn --delete /home/user/project/ /backup/project/

Lines starting with deleting in the output show what would be removed.

Sync with progress display

For large directories, add -P to see per-file progress and enable resumable transfers:

rsync -avP /home/user/project/ /backup/project/

-P is shorthand for --partial --progress . If a transfer is interrupted, --partial keeps the incomplete file so rsync can resume from where it stopped instead of starting over.

Syncing directories over SSH#

rsync uses SSH for remote transfers by default. The remote path format is the same as SCP: user@host:path .

Sync a local directory to a remote server

rsync -avz /home/user/project/ john@example.com:/var/www/html/

The -z flag compresses data during transfer, which helps on slower connections. The files are stored uncompressed at the destination.

Sync a remote directory to local

rsync -avz john@example.com:/var/www/html/ /home/user/backup/

Downloads the remote directory to your local machine. Only changed files are transferred.

Sync between remote servers

rsync does not support syncing directly between two remote servers in a single command. The standard approach is to SSH into the source server and run rsync from there:

ssh john@server1.com "rsync -avz /var/www/html/ jane@server2.com:/var/www/html/"

This transfers files directly between the two servers without routing through your local machine. For more on running commands on remote servers, see How to run commands over SSH.

Using a non-standard SSH port

If the remote server runs SSH on a port other than 22:

rsync -avz -e "ssh -p 2222" /home/user/project/ john@example.com:/var/www/html/

Using a specific SSH key

rsync -avz -e "ssh -i ~/.ssh/id_ed25519" /home/user/project/ john@example.com:/var/www/html/

If your SSH key is configured in ~/.ssh/config , rsync picks it up automatically and you do not need the -e flag.

Excluding files and directories#

Exclude by pattern

rsync -av --exclude '*.log' /home/user/project/ /backup/project/

Skips all files ending in .log .

Exclude multiple patterns

rsync -av \
  --exclude '.git' \
  --exclude 'node_modules' \
  --exclude '*.tmp' \
  /home/user/project/ /backup/project/

Exclude from a file

For complex exclusion lists, put patterns in a text file:

rsync -av --exclude-from='exclude-list.txt' /home/user/project/ /backup/project/

Where exclude-list.txt contains:

*.log
*.tmp
.git
node_modules
.env
wp-content/cache

One pattern per line. Lines starting with # are comments.

Include specific files, exclude everything else

To sync only .php files:

rsync -av --include '*/' --include '*.php' --exclude '*' source/ destination/

The --include '*/' is necessary so rsync recurses into directories. Without it, rsync excludes the directories themselves and never finds the .php files inside them.

Exclude and delete

By default, --delete does not remove files at the destination that match your exclude patterns. If you want excluded files deleted at the destination too:

rsync -av --delete --delete-excluded --exclude '*.log' source/ destination/

Practical examples#

Back up a WordPress site

rsync -avz \
  --exclude 'wp-content/cache' \
  --exclude 'wp-content/debug.log' \
  john@example.com:/var/www/html/ \
  /home/user/backups/wordpress/

Downloads the entire WordPress installation, excluding the cache directory and debug log. Run it daily and only changed files transfer each time.

Deploy code to a server

rsync -avz --delete \
  --exclude '.git' \
  --exclude '.env' \
  --exclude 'node_modules' \
  /home/user/project/ \
  john@example.com:/var/www/html/

Syncs your local project to the server. --delete removes files on the server that you deleted locally, so the server matches your local copy exactly. The exclusions prevent development artifacts from being deployed.

Sync two directories with bandwidth limit

To avoid saturating your connection during large transfers:

rsync -avz --bwlimit=5000 /home/user/project/ john@example.com:/backup/

The value is in KBytes per second. 5000 = approximately 5 MB/s.

Verify a previous sync

After a backup or migration, verify that source and destination match:

rsync -avnc source/ destination/

The -c flag compares files by checksum instead of size and timestamp. The -n flag makes it a dry run. Any files that differ are listed in the output without transferring anything.

Set permissions during sync

To enforce specific permissions at the destination:

rsync -av --chmod=D755,F644 /home/user/project/ /var/www/html/

D755 sets directories to 755 (owner rwx, others rx). F644 sets files to 644 (owner rw, others r). This is the standard permission scheme for web server files.

What rsync does not do#

rsync is a synchronization tool, not a file manager. A few things that catch people off guard:

No interactive mode. rsync is a single command that runs and exits. If you need to browse directories, rename files, or manage permissions interactively, use SFTP.

No built-in scheduling. rsync does not run on a timer by itself. To run it automatically, set up a cron job that calls your rsync command on a schedule.

One direction per command. Each rsync command syncs in one direction: source to destination. There is no bidirectional sync where changes on either side are merged. If you need that, you need a different tool or a more complex script.

rsync directory sync on Hostney#

On Hostney, rsync works over SSH with your account credentials. Every account has SSH access inside an isolated container, and rsync uses the same connection.

Connect using:

  • Host: your server hostname from the control panel
  • Port: 22
  • Username: your account username
  • Authentication: SSH key (configured through the SSH Keys section in the control panel)

Example: back up your WordPress files to your local machine:

rsync -avz user@your-server.hostney.com:/var/www/html/ /home/localuser/backups/

Deploy from local to your Hostney server:

rsync -avz --delete \
  --exclude '.git' \
  --exclude '.env' \
  /home/localuser/project/ \
  user@your-server.hostney.com:/var/www/html/

SSH key authentication is required. See the connection details under Terminal Access in the control panel.