| Tested on | RHEL 10.2 (Coughlan) — vm1.lab.example → vm2.lab.example (192.168.56.220) |
|---|---|
| Package | openssh-clients 9.9p1-25.el10_2rsync 3.4.4-1.el10_2 |
| Applies to | Ubuntu, Debian, Kali Linux, Linux Mint, Pop!_OS, Raspberry Pi OS, elementary OS, Zorin OS, Parrot OS, MX Linux, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Arch Linux |
| Privilege | SSH access to the remote host (same user or root as needed) |
| Scope | Choose between scp and rsync for remote file copy: behavior on first and repeat runs, SSH security, metadata, resume, filtering, and common path mistakes. Does not cover rsync daemon mode, lsyncd, or full backup product design. |
| Related guides | scp command rsync command ssh command Transfer files over SSH with SSHFS Copy folder local to remote with scp |
scp fits a one-off copy: you point it at a file or folder and it sends the data. rsync fits repeated synchronization: it compares source and destination, skips what already matches, and on remote transfers can update existing files with changed blocks instead of re-sending everything.
Both can run over SSH with the same login you use for remote shell access. The choice is not “which is more secure” but “do I need a simple copy once, or a sync job I will run again?”
SCP vs rsync at a glance
| Topic | scp | rsync |
|---|---|---|
| Main job | Copy files between hosts | Copy or synchronize files locally or remotely |
| Mental model | Remote cp over SSH |
Compare, then copy or skip |
| Remote transport | SSH (SFTP on current OpenSSH) | Remote shell — typically SSH with user@host:path |
| File unchanged on re-run | Sends it again | Usually skips it |
| Existing file changed | Sends whole file again | Can delta-transfer changed blocks on remote updates |
| Preserve directory metadata | Basic; use -r, -p as needed |
-a archive mode for common metadata |
| Filters / dry-run | No | --exclude, --include, -n |
| Delete extras on destination | No | --delete |
| Interrupted transfer | No built-in resume | --partial or --partial-dir can preserve partial data for the next run |
For flag syntax, use the scp and rsync cheat sheets. This page explains when each tool fits.
When to use scp
scp is OpenSSH secure file copy. The scp(1) manual describes copying between hosts over SFTP on an ssh(1) connection, with the same authentication and security as a login session.
Reach for scp when you:
- copy one file or folder once and will not repeat the job soon;
- want the smallest command with no sync options;
- do not need exclude rules, dry-run, or destination cleanup.
scp syntax
| Part | Form | Meaning |
|---|---|---|
| Command shape | scp [options] source ... destination |
Last argument is the destination; earlier paths are sources |
| Local path | /path/to/file or ./file |
Path on the machine where you run scp |
| Remote path | user@host:/path/to/file |
Path on another host; user@ is optional if it matches your local login |
| IPv6 remote path | user@[2001:db8::1]:/path |
Brackets required around the address |
Remote paths always use a colon after the host (host:). There is no trailing-slash rule like rsync — scp -r /var/www/html host:/backup/ creates /backup/html/ on the remote side.
Common scp patterns
| Task | Example |
|---|---|
| Push a file to a remote host | scp /etc/hosts root@192.168.56.220:/root/backup/hosts |
| Pull a file from a remote host | scp root@192.168.56.220:/etc/hosts ./hosts |
| Copy a directory recursively | scp -r /var/www/html root@192.168.56.220:/root/backup/ |
| Preserve times and modes | scp -p /etc/hosts root@192.168.56.220:/root/backup/hosts |
| Non-default SSH port | scp -P 2222 file root@192.168.56.220:/remote/ |
Common scp flags
| Flag | Meaning |
|---|---|
-r |
Copy directories recursively |
-p |
Preserve modification time, access time, and file modes |
-P port |
SSH port on the remote host (capital P, unlike ssh -p) |
-C |
Enable compression during transfer |
-q |
Quiet mode — hide progress meter |
Each run sends the files you named. Run the same command again tomorrow and scp sends them again, even if nothing changed.
When to use rsync
rsync behaves differently from scp. Ask rsync to copy a file again and it compares source and destination first. If a file is already unchanged, it skips it. For remote transfers, rsync can use its delta-transfer algorithm to send changed blocks of an existing file instead of retransmitting the entire file. rsync may still use whole-file transfer in some cases; --whole-file explicitly disables the delta algorithm. The rsync(1) manual describes the delta-transfer algorithm in full.
By default, rsync decides whether a file needs transfer with a quick check — mainly size and modification time. It does not checksum every unchanged file unless you add --checksum. rsync performs that comparison on each run; it does not store persistent metadata on the destination for later jobs.
Use rsync when you:
- run the same backup or deploy regularly;
- sync a directory tree and care about permissions and timestamps;
- need
--exclude,--delete, or--dry-run.
rsync syntax
| Part | Form | Meaning |
|---|---|---|
| Command shape | rsync [options] source ... destination |
Copies or syncs from source path(s) to one destination |
| Local path | /path/to/dir/ |
Ordinary filesystem path on the machine running rsync |
| Remote path | user@host:/path/to/dir/ |
Single colon (host:) — remote shell, typically SSH |
Source with trailing / |
src/ |
Copies the contents of src into the destination |
Source without trailing / |
src |
Copies the src directory itself (creates dest/src/...) |
The trailing slash on the source is one of the most common rsync mistakes. Check the destination layout before a large sync.
Common rsync patterns (remote over SSH)
| Task | Example |
|---|---|
| Sync directory contents to a remote host | rsync -av /var/www/html/ root@192.168.56.220:/root/backup/html/ |
| Pull from remote to local | rsync -av root@192.168.56.220:/remote/dir/ ./local-dir/ |
| Preview changes (no writes) | rsync -avn /var/www/html/ root@192.168.56.220:/root/backup/html/ |
| Exclude a path | rsync -av --exclude='*.log' src/ root@192.168.56.220:/dest/ |
| Mirror deletions on destination | rsync -av --delete src/ root@192.168.56.220:/dest/ |
| Keep partial file after interrupt | rsync -av --partial src/ root@192.168.56.220:/dest/ |
| Custom SSH port | rsync -av -e 'ssh -p 2222' src/ user@host:/dest/ |
The examples above often combine -av. Here is what those letters mean:
| Flag | Meaning |
|---|---|
-a |
Archive mode — preserves permissions, timestamps, ownership, symlinks, and recursion |
-v |
Verbose — lists files as rsync processes them |
-z |
Compress file data during transfer (often paired with -a as -avz) |
-e ssh |
Use ssh as the remote shell (usually optional with user@host: paths; required to pass extra SSH options such as -p 2222) |
Some metadata, such as ACLs and extended attributes, needs flags beyond -a — see the rsync command reference for those cases.
scp comes with OpenSSH and normally uses the remote SSH server's SFTP subsystem. Remote rsync additionally requires the rsync program on the remote host.
What happens when you run the command again
Unchanged file
scp copies the whole file every time.
rsync compares size and mtime. When they match, rsync skips the file and sends almost no payload. Re-run verbose rsync against a file that is already on the destination:
rsync -av /tmp/demo50m.bin root@192.168.56.220:/tmp/dest/demo50m.binSample output:
sending incremental file list
sent 61 bytes received 12 bytes 48.67 bytes/sec
total size is 52,428,800 speedup is 718,202.74The high speedup means rsync confirmed the file already matched and did not re-send the 50 MiB.
Changed file
If you edit part of a large file and run scp again, scp re-sends the entire file.
On a remote transfer, rsync detects that the file changed (quick check fails) and can use its delta-transfer algorithm to send changed blocks rather than the full file. That is where rsync saves bandwidth on large, partially updated files — not on the very first copy.
In a lab test from vm1.lab.example to vm2.lab.example, a 50 MiB file was already on the destination. Changing 5 bytes at the start and re-running each command produced:
| Tool | Wall time | Payload (approx.) |
|---|---|---|
| scp | ~2.5s | Full ~50 MiB re-sent |
rsync -av |
~1.2s | ~87 KiB sent + received (delta blocks, not the whole file) |
Re-copy the patched file with scp:
time scp -q /tmp/big50m.bin root@192.168.56.220:/tmp/dest/scp-target.binSample output:
real 0m2.500sscp transfers the whole file again even though only a few bytes changed.
Update the same destination with rsync:
time rsync -av /tmp/big50m.bin root@192.168.56.220:/tmp/dest/rsync-target.binSample output:
sending incremental file list
big50m.bin
sent 36,311 bytes received 50,729 bytes 58,026.67 bytes/sec
total size is 52,428,800 speedup is 602.35
real 0m1.240sThe sent line is far below 52 MiB because rsync moved changed blocks, not a full second copy. Exact seconds depend on your network and CPU; the pattern — scp re-sends everything, rsync sends less when part of the file already matches — is what matters.
Speed: which is faster?
There is no single winner; it depends on whether destination data already exists.
| Situation | Usually faster | Why |
|---|---|---|
| First copy to an empty destination | scp or rsync (often similar) | Both must send the full missing data; rsync may add a little protocol and file-list overhead |
| Same files, run the job again unchanged | rsync | Skips files that already match |
| Large file with a small edit | rsync | Can delta-transfer changed blocks on remote updates |
| Many small new files in a big tree | rsync | Transfers only new or changed paths |
Do not read a one-off benchmark on one VM pair as a universal rule. Cipher choice, disk cache, CPU, and network shape the seconds. The behavior in the table above is what matters in production.
Metadata, resume, filtering, and delete
| Need | scp | rsync |
|---|---|---|
| Permissions, times, symlinks on a tree | Partial; combine -r and -p |
-a for common metadata |
| Skip unchanged files on repeat runs | No | Yes (quick check by default) |
| Force content comparison before skip | No | --checksum |
| Resume after interrupted transfer | No built-in resume | --partial or --partial-dir keeps partial destination data for the next run |
| Exclude paths or preview changes | No | --exclude, -n / --dry-run |
| Remove files on destination that were deleted at source | No | --delete |
Both tools can use SSH for encrypted remote access when you write user@host:path. rsync can also use other remote shells or rsync daemon mode (host::module); this comparison stays on the SSH path most admins use alongside scp.
Common differences that cause mistakes
Trailing slash on rsync paths
This is covered in the rsync syntax table above: src/ copies contents; src copies the directory itself. List the remote destination with ssh user@host ls /dest/ before you run a long sync.
rsync must exist on the remote host
Remote rsync over user@host:path starts the rsync binary on both ends. If the remote host lacks rsync, you get command not found even though SSH works. scp comes with OpenSSH and normally uses the remote SSH server's SFTP subsystem; it does not require rsync on the remote side.
scp always re-copies; rsync is for repeat jobs
Using scp for a nightly backup of a large tree works, but every run re-sends unchanged files. rsync is the better default when the job runs on a schedule.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Permission denied on remote path |
SSH works but destination is not writable | Fix ownership or use a directory your user owns |
rsync command not found on remote |
rsync not installed on destination | Install rsync on both hosts |
| Extra nested directory on destination | rsync source path missing or extra / |
Compare src/ vs src; list remote path with ls |
| scp hangs on first connect | DNS or firewall delay | Test with ssh user@host true; try -v |
| rsync not faster on the first copy | Destination has no matching data to skip | Expected; rsync's advantage is strongest on repeated synchronization |
References
Summary
scp and rsync both move files over SSH, but they answer different questions. scp behaves like remote copy: simple, predictable, and fine for one-off transfers. rsync compares source and destination on every run, skips unchanged files, and on remote transfers can delta-transfer changed blocks when an existing file was updated.
Choose scp when you copy once and do not need sync features. Choose rsync for repeated backups, directory mirrors, filters, and jobs where most data is already on the destination. Watch rsync trailing-slash semantics and install rsync on both hosts before you rely on it remotely.
For command flags and examples, keep the scp and rsync cheat sheets handy; use this page when you need to pick the tool before you write the command.

