Skip to content

/commands/rsync/rsync-delete-mirror

rsync --delete: mirror a directory and remove extra files

The commands on this page have not been executed by our verification runner yet.updated
tool
rsync
versions
rsync 3.x
os
linux, macos

rsync -av --delete src/ dest/ makes dest an exact copy of src: it copies new and changed files and deletes files in dest that no longer exist in src. Deletion only happens inside the directories being synchronised and needs a recursive mode (-a includes -r). Because a wrong path or a missing trailing slash can delete a whole tree, preview with rsync -avn --delete src/ dest/ first, and consider --backup --backup-dir to keep deleted files.

Commands

bash
# Preview: lines starting with "deleting" are the files that would be removed
rsync -avn --delete ./site/ /var/www/site/

# Mirror locally
rsync -av --delete ./site/ /var/www/site/

# Mirror to a server, keeping deleted and overwritten files in a dated directory
rsync -av --delete --backup --backup-dir="/srv/site-trash/$(date +%F)" ./site/ deploy@server.example.com:/srv/site/

# Delete excluded files on the destination as well
rsync -av --delete --delete-excluded --exclude='*.log' ./site/ /var/www/site/

# Refuse to delete more than 100 files (exit code 25 if the limit is hit)
rsync -av --delete --max-delete=100 ./site/ /var/www/site/

Deletion options

OptionEffect
--deleteDelete extra files on the receiver; rsync 3 uses --delete-during by default
--delete-beforeDelete before transferring; frees space first, but scans the whole tree up front
--delete-during, --delDelete directory by directory during the transfer
--delete-delayFind deletions during the transfer, remove them at the end
--delete-afterDelete after all transfers in a separate pass
--delete-excludedAlso delete files on the receiver that match an exclude rule
--max-delete=NUMDelete at most NUM files; the rest are skipped and rsync exits with code 25
--max-delete=0Warn about extra files but delete none
-b --backup-dir=DIRMove deleted and replaced files into DIR instead of removing them
--ignore-errorsDelete even when there were I/O errors on the sender

Trailing slash and --delete

rsync -a --delete src/ dest/ syncs the contents of src into dest. rsync -a --delete src dest/ syncs the directory src into dest/src/ and deletes only inside dest/src/, so other files in dest survive. Mixing the two forms between runs leaves duplicate trees or deletes more than expected. The page on the rsync trailing slash shows both layouts.

Pitfalls

  • Wildcards as source. src/* passes individual names, so files deleted from src are never removed from dest.
  • Several sources. With two sources, --delete removes files in dest that exist in neither.
  • Exit codes. A run that hits --max-delete exits 25; a run with partial errors exits 23 and may have skipped deletions. Check $? in scripts.
  • Availability. rsync runs on Linux and macOS; recent macOS releases ship openrsync, which supports --delete but not every option above. On Windows use WSL or Cygwin.

Confirm the mirror

After the real run, the same command with -n -i should list nothing to transfer or delete. diff -r src dest (locally) gives an independent check.

FAQ

Does --delete remove files that I excluded?

No. Excluded files are protected from deletion on the receiver by default. Add --delete-excluded to delete them too, which is what you want when the destination should be an exact copy of what you send.

Why does rsync print IO error encountered -- skipping file deletion?

rsync found an I/O error on the sending side, for example an unreadable directory, and disabled deletion so a temporary failure cannot wipe the destination. Fix the read error, or use --ignore-errors if you are sure deletions are still safe.

Why does --delete do nothing with rsync -av src/* dest/?

The shell expands src/* into a list of files and directories, so rsync is not asked to sync the src directory itself and does not know which extra files in dest to remove. Use src/ as the source.

Sources