scp
Overview
scp (secure copy) copies files to or from a remote host over SSH. It is simple and available almost everywhere, but it is not a sync tool: every run re-transfers whole files. For large trees, resumes, and mirrors, prefer rsync over SSH. On modern OpenSSH, scp uses the SFTP protocol under the hood by default.
Syntax
scp [OPTIONS] SOURCE... DEST
# SOURCE or DEST can be: local path or [user@]host:[path]Common Options
| Option | Description |
|---|---|
-r |
Recursive (directories) |
-P port |
SSH port (capital -P; not -p) |
-i identity |
Private key file |
-C |
Compression |
-p |
Preserve mtime and modes |
-q |
Quiet (less progress noise) |
-v |
Verbose (debug SSH/auth) |
-l limit |
Bandwidth limit in kbit/s |
-o Opt=Val |
Pass SSH option (e.g. ProxyJump) |
-3 |
Copy between two remotes via local host |
Safety
scpoverwrites destination files without an interactive “are you sure?” for normal paths — double-check remote paths.- Do not embed passwords in scripts; use keys and
ssh-agent. - Recursively copying into the wrong remote directory can fill disks; test with a single file first.
- Prefer explicit paths (
user@host:/var/tmp/file) over relying on remote home defaults when automating.
Examples with Explanations
Local → remote file
scp ./report.pdf alice@server.example.com:~/uploads/Remote → local
scp alice@server:/var/log/nginx/access.log ./access.logDirectory tree
scp -r ./site alice@server:/var/www/Copies the site directory as /var/www/site (unless you structure paths carefully).
Custom port and key
scp -P 2222 -i ~/.ssh/deploy_ed25519 \
./app.tgz deploy@server:/opt/releases/Remember: -P for port on scp; ssh/rsync use -p.
Preserve times/modes
scp -p config.yml alice@server:/etc/myapp/config.ymlVia jump host (bastion)
scp -o ProxyJump=bastion.example.com \
./secret.env alice@internal:/tmp/Or with OpenSSH ProxyJump in ~/.ssh/config under a Host alias, then:
scp ./secret.env internal:/tmp/Bandwidth-limited copy
scp -l 8000 large.iso alice@server:/data/8000 ≈ 8 Mbit/s (~1 MB/s). Units are kilobits per second.
Multiple sources to a remote directory
scp a.conf b.conf c.conf alice@server:/etc/myapp/Remote-to-remote through your laptop
scp -3 alice@host-a:/data/file bob@host-b:/data/fileUseful when hosts cannot talk to each other directly.
Verbose debug when auth fails
scp -v ./file alice@server:~/Understanding Output
By default scp shows a progress meter per file (name, percent, speed, ETA). -q suppresses most of that. Failures print to stderr; non-zero exit means the copy did not fully succeed — check partial remote files.
Notes & Pitfalls
Port flag case:
scp -P 2222vsssh -p 2222. Mixing them is a common ops mistake.Spaces in paths need quoting on both local shell and careful remote escaping:
scp './My File.txt' 'alice@server:./My File.txt'scpis poor at resume: interrupt a multi-GB transfer and you usually start over. Usersync -Pinstead.Recursive
scpdoes not delete extraneous remote files (not a mirror).Older docs mention
scp’s legacy RCP-based protocol; current Ubuntu OpenSSH prefers SFTP mode. If a weird old device fails, checkman scpfor-O(legacy mode) on your version.Globs expand locally unless quoted for the remote shell.
scp server:*.log .may not do what you want; often better:ssh server 'tar czf - /var/log/*.log' | tar xzf -.
Additional Resources
man scpman ssh_config(ProxyJump, IdentityFile, Host aliases)