Rsync, SCP and SFTP compared for real Linux workflows: resume, speed, symlinks and security, plus when each tool is the right choice.
Your deploy script has pushed a build artifact to production with scp for two years. Then the artifact grows to 4GB, the connection drops at 87%, and the script restarts the whole transfer from zero while your team watches the deploy window shrink.
That is when most engineers learn that scp, sftp and rsync are not interchangeable. All three run over SSH and all three encrypt data in transit, but they were built for different jobs, and the wrong choice silently costs you time, bandwidth or a stuck deploy.
scp is a one-shot copy, sftp is an interactive file-management session, and rsync is a synchronization engine that sends only what changed. Each was designed for a different job, and that design goal should drive your choice more than command syntax.
Think of scp as cp across a network, sftp as a remote shell for files, and rsync as a diffing sync engine. Using the wrong mental model is usually why a script feels slower or clunkier than it should.
Here is the same job, copying a build directory to a server, in all three tools.
## scp: recursive copy, no resume, no diffingscp -r ./dist/ deploy@app.internal.example.net:/var/www/app ## sftp: batch mode for scripts, using a command fileprintf 'cd /var/www/app\nput -r ./dist\n' > upload.batchsftp -b upload.batch deploy@app.internal.example.net ## rsync: only changed files, resumable, compressedrsync -avz --progress ./dist/ \ deploy@app.internal.example.net:/var/www/app/Watch the trailing slash in rsync. ./dist/ copies the contents of dist into the destination, while ./dist copies the directory itself and creates dist inside it.
rsync -a (archive mode) preserves permissions, timestamps, ownership and symbolic links. scp copies file contents and, with -r, follows symlinks, so a link becomes a copy of its target. Add -p to scp if you need to preserve modes and times.
rsync compares source and destination first, then sends only what differs. By default it checks file size and modification time, and for changed files it transfers just the changed blocks. At the end it verifies the whole-file checksum.
That is why the second and later runs of a nightly sync are fast, and why a first-time copy of a single new file shows little advantage over scp.
rsync and sftp can resume, and scp cannot. If a transfer matters or the link is unreliable, use one of the first two.
## rsync: keep partial files and continue next timersync -avP large-dataset.tar.gz \ deploy@backup.internal.example.net:/backups/ ## rsync: dry run first, shows what would changersync -avn ./dist/ deploy@app.internal.example.net:/var/www/app/ ## sftp: -a resumes a partial upload or downloadprintf 'put -a large-dataset.tar.gz /backups/\n' > resume.batchsftp -b resume.batch deploy@backup.internal.example.net ## scp: a dropped transfer starts over from zeroscp large-dataset.tar.gz deploy@backup.internal.example.net:/backups/-P in rsync is shorthand for --partial --progress. Use -c only when you need checksum comparison of every file, because it reads all data on both sides and is slow.
Important: be careful with --delete, which removes files at the destination that no longer exist at the source. Always run with -n (dry run) first and double-check the source path, because a wrong path plus --delete can wipe a production directory.
All three ride on one SSH connection, and SSH uses a flow-control window. Throughput is capped at roughly the window size divided by round-trip time, so on a high-latency path the cap can sit far below your available bandwidth.
On a local network or within a region you will rarely notice. Across continents, a single stream can be many times slower than a link capable of much more. Options when that happens:
aws s3 sync or rclone, which use parallel streams.Measure with your own path and file sizes before you pick, since results depend heavily on latency, loss and file count.
Use dedicated keys with restrictions, never a shared admin login. A transfer job needs to move files, not open a shell.
## sshd_config: SFTP-only account, chrooted to its upload dirMatch User uploader ChrootDirectory /srv/uploads ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding noFor rsync jobs, restrict the key in authorized_keys with options like restrict and a forced command (for example the rrsync helper that ships with rsync), so a stolen key can only do rsync into one directory. Also store keys with strict permissions and rotate them.
Behavior comparison:
| Feature | scp | sftp |
|---|---|---|
| Resume | No | Yes |
| Interactive use | No | Yes |
| Protocol status | Legacy, uses SFTP | Active standard |
rsync and use cases:
| Feature | rsync | Best for |
|---|---|---|
| Resume | Yes, --partial |
Large or flaky links |
| Delta transfer | Yes | Repeated syncs |
| Bandwidth cap | --bwlimit |
Shared links |
For cloud storage, rclone and the cloud vendors' CLIs are usually a better fit than any SSH-based tool.
Use rsync as the default for anything that repeats: nightly backups, deploy artifact syncs and mirroring between environments. After the first run it moves only what changed.
Use sftp when a human needs to browse or manage files, or when a partner or platform only exposes an SFTP endpoint. Its audit-friendly operations and chroot support make it a good fit for controlled upload areas.
Avoid writing new automation against scp. It still works, and existing scripts do not need urgent rewriting, but rsync and sftp handle everything it does and add resume.
A few habits make any of these safer:
rsync -avn before any sync that uses --delete.--bwlimit on links shared with production traffic.-z wastes CPU on archives and images, so add --skip-compress or drop it.Related reading: rsync and sftp both run over SSH, so configuring SSH for secure server access is the foundation for either. Recurring syncs are usually scheduled, which is covered in scheduling Linux tasks with cron, and because rsync -a carries ownership and modes across, Linux file permissions and ownership explains what you will see on the destination.
References and Further Reading
- rsync Manual Page - Official flag and option reference
- OpenSSH sftp Manual - Interactive and batch mode usage
- OpenSSH Release Notes - scp moving to the SFTP protocol
- Fasterdata: Say No to scp - SSH transport limits on long paths
The old SCP protocol is considered outdated, and since OpenSSH 9.0 the scp command transfers files over SFTP by default. Existing scripts keep working and do not need urgent rewrites. For new automation, prefer rsync or sftp because they add resume support and clearer behavior.
scp has no resume mechanism: it opens a connection, copies and exits. rsync with --partial keeps the partial file so the next run continues, and sftp can resume with reget, reput or the -a option on get and put.
No. rsync's delta algorithm shines on repeated syncs where most data is unchanged. For a first copy of a single new file the speed is similar, but rsync is still the safer default because it can resume and verify the result.
A source path ending in a slash (./dist/) copies the directory's contents into the destination. Without the slash (./dist) rsync copies the directory itself, creating dist inside the destination. Mixing these up is a common way to nest folders or overwrite the wrong path, so test with --dry-run.
They run over a single SSH connection with a fixed flow-control window, and throughput is capped at roughly window size divided by round-trip time. On high-latency paths that cap sits far below your bandwidth. Parallel transfers, tuned SSH builds or object-storage tools avoid the limit.
Discussion0