DEV Community

Svyatoslav Pavlov
Svyatoslav Pavlov

Posted on Originally published at termal.in on

scp vs sftp vs rsync: which to use, with examples

All three tools ride the same SSH connection: same auth, same keys, same ~/.ssh/config aliases, same encryption. The difference is what happens after the connection opens — scp copies, sftp converses, rsync reconciles. Pick by the shape of the job and each one is excellent; pick by habit and you'll eventually re-upload 30 GB because a Wi-Fi blip killed a transfer at 97%.

scp — the one-shot copy

scp is cp with a colon in the path. For "get this file over there now," nothing beats it:

scp report.pdf deploy@web1:/srv/app/
scp deploy@web1:/var/log/app.log .
scp -r ./dist deploy@web1:/var/www/
Enter fullscreen mode Exit fullscreen mode

Three things to know before they bite:

  • The port flag is -P, capital. Lowercase -p also exists and silently does something else entirely — it preserves modification times. Everyone burns five minutes on this exactly once. Better: put Port 2222 in the host's config block and never pass either.
  • -r follows symlinks and copies what they point at, not the links themselves. A tree with links into large directories copies far more than you expect; rsync's -a preserves links as links.
  • There is no resume. An interrupted scp starts over from byte zero. That's the tool's honest scope: transfers small enough that restarting doesn't hurt.

One bonus flag: scp -3 hostA:/path/file hostB:/path/ copies between two remote hosts through your machine, so the hosts never need to trust each other. The server-to-server guide covers when that shape wins and when it doesn't.

About the deprecation you may have read about: what was deprecated is scp's ancient wire protocol — a relic inherited from 1980s rcp — not the command. Recent OpenSSH reimplemented scp on top of the SFTP protocol: same command line, saner underpinnings. Keep typing scp; nobody is taking it away. The legacy protocol is still reachable with scp -O for crusty targets that don't speak SFTP.

sftp — interactive, and the one that resumes

sftp opens a session instead of performing one copy:

sftp deploy@web1
sftp> ls -l /srv/app
sftp> get logs/app.log
sftp> put build.tar.gz /srv/app/
sftp> reget big-backup.tar.gz     # resume an interrupted download
Enter fullscreen mode Exit fullscreen mode

Two reasons to reach for it over scp:

  • You don't know the exact path yet. Browsing with ls, cd and pwd before transferring beats round-tripping full scp commands until one lands.
  • reget and reput resume interrupted transfers from the byte where the connection died. For one big file over a flaky link, this alone decides the choice.

It scripts better than its interactive reputation suggests: sftp -b commands.txt web1 runs a batch file of sftp commands and exits non-zero if any step fails — a clean fit for "upload these five files, fail loudly."

SFTP is also the protocol underneath nearly every graphical file browser — when a client shows you a remote file tree, this is what's doing the work.

rsync — sync, don't copy

rsync's premise is different from both: make the destination match the source, transferring only the difference. The first run copies everything; every later run moves only what changed — and inside big files, only the changed blocks.

rsync -avz --progress ./site/ deploy@web1:/var/www/site/
Enter fullscreen mode Exit fullscreen mode
  • -a (archive) — recursive, preserves permissions, times, and symlinks-as-symlinks; the mode you almost always want
  • -v and --progress — see what's happening; -P combines --progress with --partial, which keeps half-transferred files so the next run resumes them
  • -z — compress in transit; a win for text and code, wasted CPU on already-compressed artifacts like tarballs and images

A nonstandard port doesn't use -P (that's taken) — pass it through to SSH with -e 'ssh -p 2222', or use a config alias and forget ports exist.

The trailing-slash trap, which everyone hits once: rsync -a src/ dest/ copies the contents of src into dest, while rsync -a src dest/ creates dest/src. One character, two entirely different trees. When in doubt, add --dry-run (-n) and read the plan.

--delete deserves fear. It removes destination files that aren't in the source — exactly right for a true mirror, catastrophic with a mistyped source path, which makes the destination faithfully "match" an empty directory. House rules: never hand-typed in a hurry, always after a --dry-run shows what would go.

One requirement the others don't have: the rsync binary must exist on both ends. Nearly always true on Linux servers; frequently false on appliances and minimal containers.

The dark horse: tar over ssh

For mountains of small files, all three tools above pay per-file protocol overhead. A tar stream pays it once:

tar cf - ./node_modules | ssh deploy@web1 'tar xf - -C /srv/app/'
Enter fullscreen mode Exit fullscreen mode

No resume and no delta — but for "copy 400,000 small files somewhere once," it can beat rsync's first run outright, and it works on boxes that have nothing installed beyond tar and sshd. More patterns like this, including server-to-server without your laptop in the middle, live in the moving-files guide.

The table

scp sftp rsync
Best at one-shot copies browsing + flaky links repeated syncs, big trees
Resume no reget / reput -P, re-run to continue
Delta transfer no no yes
Needs on remote sshd sshd sshd + rsync
Danger flag -P vs -p trailing slash, --delete
Scripting fine -b batch mode excellent

Rule of thumb: one file now → scp; poke around first, or a flaky link → sftp; anything repeated or large → rsync; a zillion tiny files on a bare box → tar over ssh.

And all of them read ~/.ssh/config — a host alias with the right user, port and key, set up once, works across every tool in this post, plus git and everything else that shells out to SSH.

When a file tree beats a command line

Half of real-world transfer work isn't a clean "copy A to B" — it's find the file first, eyeball it, change one line, put it back. That's three round-trips in scp and a small ceremony in sftp. In Termalin, the SFTP browser lives next to the terminal: browse the remote tree, open a config in the built-in editor, save it straight back — no download-edit-reupload loop. For actual moving, the dual-pane file manager connects each pane independently — local↔host or host↔host — and one drag moves a file from server to server, sparing you the manual download-then-re-upload round-trip. The commands above are still worth knowing cold; the panes are for the nine transfers a day that don't deserve a command.


Termalin is a free, cross-platform SSH client with a built-in SFTP browser, file editor and dual-pane file manager — download it, or browse the full feature list.

Top comments (0)