Side by side
| scp | sftp | rsync | |
|---|---|---|---|
| Best for | One quick copy | Browsing, restricted accounts | Syncing folders, large files |
| Needs on the server | SSH with the SFTP subsystem, or scp with -O | SSH with the SFTP subsystem | SSH and rsync installed |
| Sends only changes | No | No | Yes |
| Resume | No | Yes, reget and reput | Yes, --partial |
| Port option | -P 2222 | -P 2222 | -e 'ssh -p 2222' |
scp
scp file.txt user@server:/tmp/
scp -r folder user@server:/tmp/
scp -P 2222 user@server:/var/log/app.log .
Since OpenSSH 9.0, scp uses the SFTP protocol and not the old scp protocol. You can see it with scp -v, which prints Sending subsystem: sftp. The practical gain is that file names with spaces or special characters no longer need double quoting.
If the server has no SFTP subsystem, the copy fails with subsystem request failed on channel 0. Add -O to use the old protocol:
scp -O file.txt user@server:/tmp/
More cases, such as folders, other ports and two servers, are in scp examples.
sftp
sftp user@server opens a small shell with ls, cd, get, put and bye. It works on accounts that have no shell, so it is the usual choice for restricted users. See the sftp-only user setup.
Every command at the prompt is in the list of sftp commands.
It can resume. Inside sftp, these continue a partial file:
reput big.bin /tmp/big.bin
reget /tmp/big.bin big.bin
In our test both finished from a partial file, and the checksums matched the original. For scripts, put the commands in a file and run sftp -b commands.txt user@server.
rsync
rsync -av src/ user@server:/srv/app/
rsync -avz -e 'ssh -p 2222' src/ user@server:/srv/app/
rsync -aP big.bin user@server:/tmp/
-a keeps permissions, times and links and copies folders. -v lists files. -z compresses, which helps with text on slow links. -P means --partial --progress.
rsync has to exist on both sides. Without it on the server you get:
bash: line 1: rsync: command not found
The trailing slash
A slash at the end of the source changes the result. We ran both forms on a folder src holding a.txt:
rsync -a src user@server:/tmp/noslash/ # creates /tmp/noslash/src/a.txt
rsync -a src/ user@server:/tmp/slash/ # creates /tmp/slash/a.txt
With the slash, rsync copies the contents of the folder. Without it, it copies the folder itself. A slash on the destination makes no difference.
Sending only what changed
In our test, a 50 MiB file was sent once, then 4 KiB in the middle of it was changed:
- First transfer: 52,441,699 bytes sent.
- Second transfer: 43,547 bytes sent.
This saving happens across a network. Between two folders on one machine, rsync copied the whole file again in our test.
Resuming
We stopped a transfer of that file with --partial, which left 15.4 MB at the destination. Running the same command again reused those bytes and sent the rest, and cmp found the result identical to the original. Without --partial, rsync removes the partial file when it is interrupted.
Two traps
- rsync may skip a changed file. By default it compares only size and modification time. In our first test the 4 KiB change landed within the same second as the earlier copy, with the same size, and rsync sent nothing.
-ccompares checksums, at the cost of reading every file. --deleteremoves files at the destination that are not in the source. With a wrong path, that can be a lot of files. Add-nfirst to see the list:rsync -avn --delete src/ user@server:/srv/app/.
On recent macOS, /usr/bin/rsync may be openrsync and not the original: on our test Mac rsync --version printed openrsync: protocol version 29. The options above worked, but it does not have everything, so check the output of rsync --version if an option is refused.
Which to choose
- One file, once:
scp. - You need to look around first, or the account allows only SFTP:
sftp. - The same folder again and again, or a large file on a bad connection:
rsync. - Your local editor and tools on server files: mount the folder with sshfs.
All three read your SSH config, so a Host entry saves the port and user. See the SSH config file.
Questions
Is SFTP the same as scp?
No. sftp is an interactive client for browsing and transferring files, and scp is a one-line copy command. Since OpenSSH 9.0, scp uses the SFTP protocol underneath.
Is rsync faster than scp?
When the destination already has an older copy, yes: rsync sends only the changed parts. In our test, a 4 KiB change in a 50 MiB file sent about 43 KB. For a new file, both send the whole file.
Does rsync work over SSH?
Yes. For a remote path rsync connects with ssh by default, but rsync must also be installed on the server.
Sources
- OpenSSH 9.0 release notes
- scp(1), OpenBSD manual
- sftp(1), OpenBSD manual
- rsync(1) manual
- How rsync works