Skip to main content

How to Use SCP to Transfer Files Over SSH

·614 words·3 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.

What is SCP?
#

SCP (Secure Copy Protocol) transfers files between hosts over an SSH connection. It uses the same authentication and encryption as SSH, so if you can ssh into a machine, you can scp files to and from it.

scp file.txt user@remote:/path/to/destination/

That’s the core pattern: scp <source> <destination>, where either side can be a remote host.

Basic Syntax
#

scp [options] <source> <destination>

Remote paths use the format user@host:/path. Local paths are just regular file paths.

DirectionCommand
Local → Remotescp file.txt user@server:/tmp/
Remote → Localscp user@server:/tmp/file.txt ./
Remote → Remotescp user@server1:/tmp/file.txt user@server2:/tmp/

Key Options
#

-r — Recursive (directories)
#

Copy an entire directory and its contents:

scp -r ./project/ user@server:/home/user/project/

Without -r, attempting to copy a directory will fail.

-P — Port
#

Connect on a non-standard SSH port (note: uppercase -P, unlike ssh which uses lowercase -p):

scp -P 2222 file.txt user@server:/tmp/

-i — Identity file
#

Use a specific SSH private key:

scp -i ~/.ssh/deploy_key app.tar.gz user@server:/opt/releases/

-C — Compression
#

Compress data during transfer. Useful on slow connections with compressible data:

scp -C largefile.sql user@server:/backups/

-l — Bandwidth limit
#

Limit bandwidth in Kbit/s. Prevents saturating the connection:

# Limit to 5000 Kbit/s (~625 KB/s)
scp -l 5000 backup.tar.gz user@server:/backups/

-q — Quiet mode
#

Suppress the progress bar and non-error messages:

scp -q file.txt user@server:/tmp/

-o — SSH options
#

Pass any SSH configuration option directly:

scp -o StrictHostKeyChecking=no file.txt user@server:/tmp/

Practical Examples
#

Deploy a build artifact to a server
#

scp -i ~/.ssh/deploy_key dist/app-v1.2.0.tar.gz deploy@prod:/opt/releases/

Pull logs from a remote server
#

scp user@server:/var/log/app/error.log ./error-$(date +%F).log

Copy a directory to a remote host
#

scp -r ./configs/ user@server:/etc/myapp/

Transfer between two remote servers
#

scp user@server1:/backups/db.sql.gz user@server2:/backups/

Note: this routes traffic through your local machine by default. Both servers must be reachable from your workstation.

Use with SSH config aliases
#

If your ~/.ssh/config defines a host:

Host prod
    HostName 10.0.1.50
    User deploy
    IdentityFile ~/.ssh/deploy_key
    Port 2222

Then you can simply:

scp dist/app.tar.gz prod:/opt/releases/

Copy multiple files
#

scp file1.txt file2.txt user@server:/tmp/

# Or use a glob
scp *.log user@server:/backups/logs/

Using Wildcards on Remote Paths
#

To copy files matching a pattern from a remote host, quote the path to prevent local shell expansion:

scp user@server:"/var/log/app/*.log" ./logs/

Without quotes, your local shell expands the * before SCP sees it.

Troubleshooting
#

Permission denied
#

# Check you can SSH to the host first
ssh user@server

# Verify the destination directory is writable
ssh user@server 'ls -ld /path/to/destination/'

Connection refused or timeout
#

# Test SSH connectivity
ssh -v user@server

# Verify the port
nc -zv server 22

Slow transfers
#

# Enable compression
scp -C largefile user@server:/tmp/

# Check if the bottleneck is network or disk
ssh user@server 'dd if=/dev/zero bs=1M count=100' | pv > /dev/null

Host key verification failed
#

This usually means the server’s key changed (reinstall, IP reuse). Verify the change is expected, then:

ssh-keygen -R server

SCP vs Alternatives
#

ToolBest For
scpQuick one-off transfers, simple syntax
rsyncIncremental sync, resumable, better for large/repeated transfers
sftpInteractive file browsing, resume support
ssh + tarPreserving permissions/ownership, streaming directories

For recurring or large transfers, rsync is generally preferred:

# rsync equivalent of scp -r
rsync -avz ./project/ user@server:/home/user/project/

Best Practices
#

  • Use SSH keys instead of passwords for all SCP operations
  • Prefer rsync for repeated or large transfers — it only sends differences
  • Always quote remote wildcards to avoid local shell expansion
  • Set up ~/.ssh/config aliases to avoid retyping hosts, ports, and key paths
  • Use -l to limit bandwidth on shared or production connections
  • Verify transfers with checksums when integrity matters: sha256sum on both sides